Difference between revisions of "Unsafe functions"
m (Initial quote replaced) |
(...a more suitable word does exist! :-D) |
||
(One intermediate revision by the same user not shown) | |||
Line 1: | Line 1: | ||
+ | {{DISPLAYTITLE:<span style="position: absolute; clip: rect(1px 1px 1px 1px); clip: rect(1px, 1px, 1px, 1px);">{{FULLPAGENAME}}</span>}} |
||
+ | <font size="+3" face="Times New Roman">Unsafe perforatives</font> |
||
+ | |||
<blockquote> |
<blockquote> |
||
[Using the FFI] you can import any C function with a pure type, |
[Using the FFI] you can import any C function with a pure type, |
||
Line 9: | Line 12: | ||
</blockquote> |
</blockquote> |
||
+ | == Definitely '''not''' functions! == |
||
− | There are a number of '''unsafe functions''' in the libraries. |
||
+ | |||
+ | Regarding the perforative entity <code>val execute: α Beh ⟶ α</code> for PFL+: |
||
+ | |||
+ | <blockquote> |
||
+ | Unfortunately <code>execute</code> is not a safe extension to a functional language because it is not unfoldable—witness the expression |
||
+ | |||
+ | <pre> |
||
+ | (x ⟼ x-x)(execute(i?x. Ret x)) |
||
+ | </pre> |
||
+ | |||
+ | which unfolds to |
||
+ | |||
+ | <pre> |
||
+ | execute(i?x. Ret x) - execute(i?x. Ret x) |
||
+ | </pre> |
||
+ | |||
+ | The first executes by reading one value from channel <code>i</code>, then returning <code>0</code>; while the second reads two values from <code>i</code>, and returns their difference. The first makes one suspension, the second two. |
||
+ | |||
+ | Nor is <code>execute</code> a function; the subexpression <code>execute(i?x. Ret x)</code> can take on two different values in the expression above. |
||
+ | |||
+ | :<small>[https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-160.pdf PFL+: A Kernel Scheme for Functional I/O] (pages 15-16 of 28).</small> |
||
+ | </blockquote> |
||
+ | |||
+ | == A rogues' gallery == |
||
+ | |||
+ | These are just some of the various unsafe perforatives lurking in libraries: |
||
* <hask>unsafeLocalState :: IO a -> a</hask> |
* <hask>unsafeLocalState :: IO a -> a</hask> |
||
Line 21: | Line 50: | ||
* <hask>unsafeCoerce# :: a -> b</hask> |
* <hask>unsafeCoerce# :: a -> b</hask> |
||
− | Unsafe |
+ | Unsafe perforatives can: |
* break type safety (<code>unsafeCoerce#</code>, <code>unsafeLocalState</code>, <code>unsafePerformIO</code>), |
* break type safety (<code>unsafeCoerce#</code>, <code>unsafeLocalState</code>, <code>unsafePerformIO</code>), |
||
Line 27: | Line 56: | ||
* or break [https://okmij.org/ftp/Haskell/index.html#lazyIO-not-True equational reasoning] (<code>unsafeInterleaveIO</code>). |
* or break [https://okmij.org/ftp/Haskell/index.html#lazyIO-not-True equational reasoning] (<code>unsafeInterleaveIO</code>). |
||
− | Their use would require some kind of assurance on the part of the programmer that what they're doing is safe. |
+ | Their use would require some kind of assurance on the part of the programmer that what they're doing is safe, particularly in multithreaded programs - if they are misused in vain attempts to hide externally-visible effects the resulting code simply will not be [[Pure|pure]], whatever type it is given. |
+ | |||
+ | ---- |
||
<code>unsafe</code> is also a keyword which can be used in a [http://haskell.org/haskellwiki/Performance/FFI foreign import declaration]. |
<code>unsafe</code> is also a keyword which can be used in a [http://haskell.org/haskellwiki/Performance/FFI foreign import declaration]. |
||
+ | |||
{{stub}} |
{{stub}} |
Latest revision as of 08:31, 10 October 2024
Unsafe perforatives
[Using the FFI] you can import any C function with a pure type, which also allows you to wreak arbitrary havoc. We enable the user to disguise arbitrary machine code as a Haskell function of essentially arbitrary type. In comparison,
unsafePerformIO
seems angelic.
Definitely not functions!
Regarding the perforative entity val execute: α Beh ⟶ α
for PFL+:
Unfortunately
execute
is not a safe extension to a functional language because it is not unfoldable—witness the expression(x ⟼ x-x)(execute(i?x. Ret x))which unfolds to
execute(i?x. Ret x) - execute(i?x. Ret x)The first executes by reading one value from channel
i
, then returning0
; while the second reads two values fromi
, and returns their difference. The first makes one suspension, the second two.Nor is
execute
a function; the subexpressionexecute(i?x. Ret x)
can take on two different values in the expression above.
- PFL+: A Kernel Scheme for Functional I/O (pages 15-16 of 28).
A rogues' gallery
These are just some of the various unsafe perforatives lurking in libraries:
unsafeLocalState :: IO a -> a
unsafePerformIO :: IO a -> a
inlinePerformIO :: IO a -> a
unsafeInterleaveIO :: IO a -> IO a
unsafeInterleaveST :: ST s a -> ST s a
unsafeIOToST :: IO a -> ST s a
unsafeIOToSTM :: IO a -> STM a
unsafeFreeze
,unsafeThaw
unsafeCoerce# :: a -> b
Unsafe perforatives can:
- break type safety (
unsafeCoerce#
,unsafeLocalState
,unsafePerformIO
),
- or break equational reasoning (
unsafeInterleaveIO
).
Their use would require some kind of assurance on the part of the programmer that what they're doing is safe, particularly in multithreaded programs - if they are misused in vain attempts to hide externally-visible effects the resulting code simply will not be pure, whatever type it is given.
unsafe
is also a keyword which can be used in a foreign import declaration.
This article is a stub. You can help by expanding it.