SafeHaskell: Added SafeHaskell to base
[ghc.git] / libraries / base / Control / Monad / ST / Lazy / Imp.hs
1 {-# LANGUAGE CPP, MagicHash, UnboxedTuples, Rank2Types #-}
2 {-# OPTIONS_HADDOCK hide #-}
3
4 -----------------------------------------------------------------------------
5 -- |
6 -- Module : Control.Monad.ST.Lazy.Imp
7 -- Copyright : (c) The University of Glasgow 2001
8 -- License : BSD-style (see the file libraries/base/LICENSE)
9 --
10 -- Maintainer : libraries@haskell.org
11 -- Stability : provisional
12 -- Portability : non-portable (requires universal quantification for runST)
13 --
14 -- This module presents an identical interface to "Control.Monad.ST",
15 -- except that the monad delays evaluation of state operations until
16 -- a value depending on them is required.
17 --
18 -----------------------------------------------------------------------------
19
20 -- #hide
21 module Control.Monad.ST.Lazy.Imp (
22 -- * The 'ST' monad
23 ST,
24 runST,
25 fixST,
26
27 -- * Converting between strict and lazy 'ST'
28 strictToLazyST, lazyToStrictST,
29
30 -- * Converting 'ST' To 'IO'
31 RealWorld,
32 stToIO,
33
34 -- * Unsafe operations
35 unsafeInterleaveST,
36 unsafeIOToST
37 ) where
38
39 import Prelude
40
41 import Control.Monad.Fix
42
43 import qualified Control.Monad.ST.Safe as ST
44 import qualified Control.Monad.ST.Unsafe as ST
45
46 #ifdef __GLASGOW_HASKELL__
47 import qualified GHC.ST as GHC.ST
48 import GHC.Base
49 #endif
50
51 #ifdef __HUGS__
52 import Hugs.LazyST
53 #endif
54
55 #ifdef __GLASGOW_HASKELL__
56 -- | The lazy state-transformer monad.
57 -- A computation of type @'ST' s a@ transforms an internal state indexed
58 -- by @s@, and returns a value of type @a@.
59 -- The @s@ parameter is either
60 --
61 -- * an unstantiated type variable (inside invocations of 'runST'), or
62 --
63 -- * 'RealWorld' (inside invocations of 'stToIO').
64 --
65 -- It serves to keep the internal states of different invocations of
66 -- 'runST' separate from each other and from invocations of 'stToIO'.
67 --
68 -- The '>>=' and '>>' operations are not strict in the state. For example,
69 --
70 -- @'runST' (writeSTRef _|_ v >>= readSTRef _|_ >> return 2) = 2@
71 newtype ST s a = ST (State s -> (a, State s))
72 data State s = S# (State# s)
73
74 instance Functor (ST s) where
75 fmap f m = ST $ \ s ->
76 let
77 ST m_a = m
78 (r,new_s) = m_a s
79 in
80 (f r,new_s)
81
82 instance Monad (ST s) where
83
84 return a = ST $ \ s -> (a,s)
85 m >> k = m >>= \ _ -> k
86 fail s = error s
87
88 (ST m) >>= k
89 = ST $ \ s ->
90 let
91 (r,new_s) = m s
92 ST k_a = k r
93 in
94 k_a new_s
95
96 {-# NOINLINE runST #-}
97 -- | Return the value computed by a state transformer computation.
98 -- The @forall@ ensures that the internal state used by the 'ST'
99 -- computation is inaccessible to the rest of the program.
100 runST :: (forall s. ST s a) -> a
101 runST st = case st of ST the_st -> let (r,_) = the_st (S# realWorld#) in r
102
103 -- | Allow the result of a state transformer computation to be used (lazily)
104 -- inside the computation.
105 -- Note that if @f@ is strict, @'fixST' f = _|_@.
106 fixST :: (a -> ST s a) -> ST s a
107 fixST m = ST (\ s ->
108 let
109 ST m_r = m r
110 (r,s') = m_r s
111 in
112 (r,s'))
113 #endif
114
115 instance MonadFix (ST s) where
116 mfix = fixST
117
118 -- ---------------------------------------------------------------------------
119 -- Strict <--> Lazy
120
121 #ifdef __GLASGOW_HASKELL__
122 {-|
123 Convert a strict 'ST' computation into a lazy one. The strict state
124 thread passed to 'strictToLazyST' is not performed until the result of
125 the lazy state thread it returns is demanded.
126 -}
127 strictToLazyST :: ST.ST s a -> ST s a
128 strictToLazyST m = ST $ \s ->
129 let
130 pr = case s of { S# s# -> GHC.ST.liftST m s# }
131 r = case pr of { GHC.ST.STret _ v -> v }
132 s' = case pr of { GHC.ST.STret s2# _ -> S# s2# }
133 in
134 (r, s')
135
136 {-|
137 Convert a lazy 'ST' computation into a strict one.
138 -}
139 lazyToStrictST :: ST s a -> ST.ST s a
140 lazyToStrictST (ST m) = GHC.ST.ST $ \s ->
141 case (m (S# s)) of (a, S# s') -> (# s', a #)
142 #endif
143
144 -- | A monad transformer embedding lazy state transformers in the 'IO'
145 -- monad. The 'RealWorld' parameter indicates that the internal state
146 -- used by the 'ST' computation is a special one supplied by the 'IO'
147 -- monad, and thus distinct from those used by invocations of 'runST'.
148 stToIO :: ST RealWorld a -> IO a
149 stToIO = ST.stToIO . lazyToStrictST
150
151 -- ---------------------------------------------------------------------------
152 -- Strict <--> Lazy
153
154 #ifdef __GLASGOW_HASKELL__
155 unsafeInterleaveST :: ST s a -> ST s a
156 unsafeInterleaveST = strictToLazyST . ST.unsafeInterleaveST . lazyToStrictST
157 #endif
158
159 unsafeIOToST :: IO a -> ST s a
160 unsafeIOToST = strictToLazyST . ST.unsafeIOToST
161
162