2.5 Monad Transformers
(require hackett/monad/trans) | package: hackett-lib |
The class of monad transformers. A monad transformer builds a new monad from an existing
one, extending it with additional functionality. In this sense, monad transformers can be thought of
as “monad mixins”.
Instances should satisfy the following laws:
{lift . pure} = pure (lift {m >>= f}) = {(lift m) >>= {lift . f}}
Lifts a computation from the argument monad to the constructed monad.
2.5.1 Base Monads
(require hackett/monad/base) | package: hackett-lib |
typeclass
(class (Monad m) => (Monad-Base b m)
#:fundeps [
[m -> b]] [lift/base : (forall [a] {(b a) -> (m a)})])
A class for access the base monad in a monad transformer
stack. Instances should satisfy the following laws:
{lift/base . pure} = pure {lift/base {m >>= f}} = {(lift/base m) >>= {lift . f}}
Lifts a computation from the base monad b into m. For base monads, like IO, lift/base should be id, and for monad transformers, it should be {lift . lift/base}.
2.5.2 Reader
(require hackett/monad/reader) | package: hackett-lib |
typeclass
(class (Monad m) => (Monad-Reader r m)
#:fundeps [
[m -> r]] [ask : (m r)] [local : (forall [a] {{r -> r} -> (m a) -> (m a)})] [reader : (forall [a] {{r -> a} -> (m a)})])
The class of monads that support reading values from a read-only
implicit environment. The environment can be accessed with ask and locally modified with
local.
value
ask : (m r)
A computation that fetches the value of the current dynamic environment.
> (run-reader ask 5)
: Integer
5
> (run-reader ask "hello")
: String
"hello"
Produces a computation that fetches a value from the current dynamic environment, applies f to it, and returns the result.
> (run-reader (asks (+ 1)) 5)
: Integer
6
> (run-reader (asks head) {5 :: Nil})
: (Maybe Integer)
(Just 5)
Given a function f and a computation x, produces a computation like x, except that its environment is modified by applying f to it.
An alias for reader.
The reader monad transformer, a monad transformer that implements the
Monad-Reader class to add support for reading values from a read-only implicit environment
to an existing monad.
> (run-reader/t (do [x <- ask] [y <- (lift {{x + 1} :: {x - 1} :: Nil})] (lift {{y * 2} :: {y * 3} :: Nil})) 10)
: (List Integer)
{22 :: 33 :: 18 :: 27 :: Nil}
procedure
(run-reader/t x ctx) → (m a)
x : (Reader/T r m a) ctx : r
Runs the reader monad transformer computation x with the context ctx and
produces a computation in the argument monad.
procedure
(run-reader x ctx) → a
x : (Reader/T r Identity a) ctx : r
2.5.3 Error
(require hackett/monad/error) | package: hackett-lib |
typeclass
(class (Monad m) => (Monad-Error e m)
#:fundeps [
[m -> e]] [throw : (forall [a] {e -> (m a)})] [catch : (forall [a] {(m a) -> {e -> (m a)} -> (m a)})])
The class of monads that support a notion of failure. Failures
short-circuit other computations in the monad, and they can carry information, usually information
about what caused the failure.
Produces a computation that raises the given value as an error, aborting the current computation (unless caught with catch).
> (: (run-error (pure 42)) (Either String Integer))
: (Either String Integer)
(Right 42)
> (run-error (do (throw "Ack!") (pure 42)))
: (Either String Integer)
(Left "Ack!")
Produces a computation like the given one, except any errors raised are handled via the given handler function instead of immediately aborting.
> (: (run-error (throw "Ack!")) (Either String String))
: (Either String String)
(Left "Ack!")
> (run-error (catch (throw "Ack!") (λ [str] (pure {"Caught error: " ++ str}))))
: (Either String String)
(Right "Caught error: Ack!")
The error monad transformer, a monad transformer that implements the
Monad-Error class to extend a monad with a notion of failure.
> (run-error/t (do (lift (println "This gets printed.")) (throw "Oops!") (lift (println "Never gets here.")))) This gets printed.
: (Either String Unit)
(Left "Oops!")
procedure
(run-error/t x) → (m (Either e a))
x : (Error/T e m a)
Runs the error monad transformer computation x and produces the possibly-aborted
result in the argument monad.
Runs the error monad transformer computation x and extracts the possibly-aborted
result.