1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
<sect> <idx/IOExts/
<label id="sec:IOExts">
<p>
This library provides the following extensions to the IO monad:
<itemize>
<item>
The operations <tt/fixIO/, <tt/unsafePerformIO/ and <tt/unsafeInterleaveIO/
described in <cite id="ImperativeFP">
<item>
References (aka mutable variables) and mutable arrays (but no form of
mutable byte arrays)
<item>
<tt/openFileEx/ extends the standard <tt/openFile/ action with support
for opening binary files.
<item>
<tt/performGC/ triggers an immediate garbage collection
<item>
When called, <tt/trace/ prints the string in its first argument to
standard error, before returning the second argument as its result.
The <tt/trace/ function is not referentially transparent, and should
only be used for debugging, or for monitoring execution. Some
implementations of <tt/trace/ may decorate the string that's output
to indicate that you're tracing.
<!--
You should also be warned that, unless you understand some of the
details about the way that Haskell programs are executed, results
obtained using <tt/trace/ can be rather confusing. For example, the
messages may not appear in the order that you expect. Even ignoring the
output that they produce, adding calls to <tt/trace/ can change the
semantics of your program. Consider this a warning!
-->
<item>
<tt/unsafePtrEq/ compares two values for pointer equality without
evaluating them. The results are not referentially transparent and
may vary significantly from one compiler to another or in the face of
semantics-preserving program changes. However, pointer equality is useful
in creating a number of referentially transparent constructs such as this
simplified memoisation function:
<tscreen><verb>
> cache :: (a -> b) -> (a -> b)
> cache f = \x -> unsafePerformIO (check x)
> where
> ref = unsafePerformIO (newIORef (error "cache", error "cache"))
> check x = readIORef ref >>= \ (x',a) ->
> if x `unsafePtrEq` x' then
> return a
> else
> let a = f x in
> writeIORef ref (x, a) >>
> return a
</verb></tscreen>
</itemize>
<tscreen><verb>
module IOExts where
fixIO :: (a -> IO a) -> IO a
unsafePerformIO :: IO a -> a
unsafeInterleaveIO :: IO a -> IO a
data IORef a -- mutable variables containing values of type a
newIORef :: a -> IO (IORef a)
readIORef :: IORef a -> IO a
writeIORef :: IORef a -> a -> IO ()
instance Eq (IORef a)
data IOArray ix elt -- mutable arrays indexed by values of type ix
-- containing values of type a.
newIOArray :: Ix ix => (ix,ix) -> elt -> IO (IOArray ix elt)
boundsIOArray :: Ix ix => IOArray ix elt -> (ix, ix)
readIOArray :: Ix ix => IOArray ix elt -> ix -> IO elt
writeIOArray :: Ix ix => IOArray ix elt -> ix -> elt -> IO ()
freezeIOArray :: Ix ix => IOArray ix elt -> IO (Array ix elt)
instance Eq (IOArray ix elt)
openFileEx :: FilePath -> IOModeEx -> IO Handle
data IOModeEx = BinaryMode IO.IOMode | TextMode IO.IOMode
instance Eq IOModeEx
instance Read IOModeEx
instance Show IOModeEx
performGC :: IO ()
trace :: String -> a -> a
unsafePtrEq :: a -> a -> Bool
</verb></tscreen>
|