The Monad class defines the basic operations over a monad, a concept from a branch of mathematics known as category theory. From the perspective of a Haskell programmer, however, it is best to think of a monad as an abstract datatype of actions. Haskell's do expressions provide a convenient syntax for writing monadic expressions.
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
return :: a -> m a
fail :: String -> m a
(>>=)
Sequentially compose two actions, passing any value produced by the first as an argument to the second.(>>)
Sequentially compose two actions, discarding any value produced by the first, like sequencing operators (such as the semicolon) in imperative languages(return)
Inject a value into the monadic type(fail)
Fail with a message. This operation is not part of the mathematical definition of a monad, but is invoked on pattern-match failure in a do expression.
A minimal complete definition of the Monad class requires implementing >>=
and return
, since
m >> k = m >>= \_ -> k
fail s = error s
Instances of Functor should satisfy the following laws.
fmap id == id
fmap (f . g) == fmap f . fmap g
Instances of Monad should satisfy the following laws.
return a >>= k == k a
m >>= return == m
m >>= (\x -> k x >>= h) == (m >>= k) >>= h
Instances of both 'Monad' and 'Functor' should additionally satisfy the law:
fmap f xs == xs >>= return . f
The Maybe
type encapsulates an optional value. The Maybe
type is a
simple kind of error monad where all of the errors are represented by
Nothing
.
data Maybe a = Nothing | Just a
maybe :: b -> (a -> b) -> Maybe a -> b
maybe n f Nothing = n
maybe n f (Just x) = f x
instance Functor Maybe where
fmap f Nothing = Nothing
fmap f (Just x) = Just (f x)
instance Monad Maybe where
(Just x) >>= k = k x
Nothing >>= k = Nothing
return = Just
fail s = Nothing
-- not valid Haskell; for illustration only
data [a] = [] | a : [a]
instance Functor [] where
fmap = map
instance Monad [] where
m >>= k = concat (map k m)
return x = [x]
fail s = []
A value of type IO a
is a computation which, when performed, does some
I/O before returning a value of type a
.
The only way to perform an I/O action is to bind it to Main.main
in
your program. It isn't possible to perform I/O from an arbitrary
function, unless that function is itself in the IO
monad and called
directly or indirectly from Main.main
.
-- abstract
data IO a = ...
instance Functor IO where
fmap f x = x >>= (return . f)
instance Monad IO where
(>>=) = ...
return = ...
fail s = ioError (userError s)
-- related functions
userError :: String -> IOError
ioError :: IOError -> IO a
catch :: IO a -> (IOError -> IO a) -> IO a
The two monadic binding functions, methods in the Monad class, are used
to compose a series of I/O operations. The >>
function is used where
the result of the first operation is uninteresting, for example when it
is ()
. The >>=
operation passes the result of the first operation as
an argument to the second operation.
As an example of IO usage, the following program reads in an input file, filters out everything that isn't ascii, writes it to an output file, and prints a message that it was successful.
main = readFile "input-file" >>= \s ->
writeFile "output-file" (filter isAscii s) >>
putStrLn "Filtering successful"
In do notation, this reads
main = do
s <- readFile "input-file"
writeFile "output-file" (filter isAscii s)
putStrLn "Filtering successful"
A do expression provides a more conventional syntax for monadic programming. It allows an expression such as
putStr "x: " >>
getLine >>= \l ->
return (words l)
to be written in a more traditional way as:
do putStr "x: "
l <- getLine
return (words l)
It can also be written using semicolons as follows
do { putStr "x: "; l <- getLine; return (words l) }
mapM f
is equivalent to sequence . map f
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
mapM_ f
is equivalent to sequence_ . map f
mapM_ :: Monad m => (a -> m b) -> [a] -> m ()
forM
is mapM
with its arguments flipped
forM :: Monad m => [a] -> (a -> m b) -> m [b]
forM_
is mapM_
with its arguments flipped
forM_ :: Monad m => [a] -> (a -> m b) -> m ()
Evaluate each action in the sequence from left to right, and collect the results
sequence :: Monad m => [m a] -> m [a]
Evaluate each action in the sequence from left to right, and ignore the results
sequence_ :: Monad m => [m a] -> m ()
Same as >>=
, but with the arguments interchanged
(=<<) :: Monad m => (a -> m b) -> m a -> m b
Left-to-right Kleisli composition of monads
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
Right-to-left Kleisli composition of monads. (>=>)
with the arguments
flipped
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
forever act
repeats the action indefinitiely
forever :: Monad m => m a -> m b
void value
discards or ignores the result of evaluation, such as the
return value of an IO
action
void :: Functor f => f a -> f ()