2 % (c) The GRASP/AQUA Project, Glasgow University, 1994
4 \section[PrelMonIO]{Monadic I/O Primitives}
6 This module defines the basic monadic framework for Haskell 1.3 I/O.
10 module PreludeMonadicIO (
33 import Prel ( (.), not )
34 import PS ( _PackedString, _unpackPS )
44 \subsection[IOMonad]{The IO Monad}
46 I/O operations may need to indicate errors, and implementations may
47 need to handle these errors. The $IO$ monad extends existing practice
48 by making this functionality primitive. The exact errors which may
49 occur are defined in $PreludeIOError13$.
53 type IO a = PrimIO (Either IOError13 a)
55 data Either a b = Left a | Right b deriving (Text, Eq, Ord)
59 An expression of type $IO a$, for some type {\em a}, denotes a
60 computation whose answer is either a result of type {\em a} or an
61 <em>error</em> of type $IOError13$. The computation succeeds with
62 result {\em succ} if its answer is $Right succ$, and fails with
63 result {\em fail} if its answer is $Left fail$. Note that the
64 type system delimits the possibility of failure: only expressions of
65 some type $IO a$ can <em>fail</em> in the sense defined here.
70 {-# INLINE failWith #-}
73 failWith :: IOError13 -> IO a
75 return = returnPrimIO . Right
76 failWith = returnPrimIO . Left
80 There are two primitives to create trivial computations, one for
81 each of the two possibilities, success or failure.
83 $return result$ is a computation that succeeds with result
86 $failWith fail$ is a computation that fails with the error
93 (>>=) :: IO a -> (a -> IO b) -> IO b
94 m >>= k = m `thenPrimIO` \ r -> k' r
97 k' (Left err) = returnPrimIO (Left err)
101 The $>>=$ operation is used to sequence two computations, where the
102 second computation is parameterised on the result of the first.
108 (>>) :: IO a -> IO b -> IO b
109 m >> k = m >>= \ _ -> k
113 The restricted form of $>>=$, $>>$, is used when the result of the
114 first computation is uninteresting.
116 \subsection[Error-Handling]{Error Handling}
120 handle :: IO a -> (IOError13 -> IO a) -> IO a
121 handle m k = m `thenPrimIO` \ r -> k' r
123 k' (Left err) = k err
124 k' result = returnPrimIO result
128 The construct $handle comp handler$ can be used to handle a
129 simple error during a computation {\em comp}. Its usefulness is
130 limited in that the replacement value must be of the same type as the
131 result of {\em comp}.
135 try :: IO a -> IO (Either IOError13 a)
136 try p = handle (p >>= (return . Right)) (return . Left)
140 The construct $try comp$ exposes errors which occur within a
141 computation, and which are not fully handled. It always succeeds.
143 \subsection[UserErrors]{User-Defined Errors}
147 fail :: String -> IO a
148 fail = failWith . UserError
152 As a convention for user-generated errors, to return an error message
153 $msg :: String$, return the error value $UserError msg$
154 via the computation $fail msg$.
156 This construct should be used instead of Haskell's $error :: String -> a$
157 operation wherever convenient.
159 \subsection[HOFs]{Higher-Order Utility Functions}
163 either :: (a -> c) -> (b -> c) -> (Either a b) -> c
164 either kl kr x = case x of {Left a -> kl a; Right b -> kr b}
168 The construct $either a b$ can be used to generate functions on types
169 of the form $Either a b$.
173 accumulate :: [IO a] -> IO [a]
175 accumulate [] = return []
178 accumulate fs >>= \ xs ->
181 {- partain: this may be right, but I'm going w/ a more-certainly-right version
182 accumulate = foldr mcons (return [])
184 mcons :: IO a -> IO [a] -> IO [a]
185 mcons p q = p >>= \x -> q >>= \y -> return (x : y)
190 The $accumulate$ computation is used to process a list of computations
191 of the same type, and to return a list of their results when executed
196 sequence :: [IO a] -> IO ()
197 sequence = foldr (>>) (return ())
201 The $sequence$ computation is used for the simpler case when the
202 computations are executed entirely for their external effect, and the
203 results are therefore uninteresting.