On this page:
Monad-Trans
lift
2.5.1 Base Monads
Monad-Base
lift/  base
2.5.2 Reader
Monad-Reader
ask
reader
local
asks
Reader/  T
Reader/  T
run-reader/  t
run-reader
2.5.3 Error
Monad-Error
throw
catch
Error/  T
Error/  T
run-error/  t
run-error

2.5 Monad Transformers

 (require hackett/monad/trans) package: hackett-lib

typeclass

(class (Monad-Trans t)

  [lift : (forall [m a] {(m a) -> (t m a)})])
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}}

value

lift : (forall [m a] {(m a) -> (t m a)})

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}}

value

lift/base : (forall [a] {(b a) -> (m a)})

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"

value

reader : (forall [a] {{r -> a} -> (m a)})

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)

value

local : (forall [a] {{r -> r} -> (m a) -> (m a)})

Given a function f and a computation x, produces a computation like x, except that its environment is modified by applying f to it.

value

asks

 : (forall [r m a] (Monad-Reader r m) => {{r -> a} -> (m a)})
An alias for reader.

datatype

(data (Reader/T r m a)
  (Reader/T {r -> (m a)}))
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
Runs the reader monad transformer computation x with the context ctx and extracts the result.

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.

value

throw : (forall [a] {e -> (m a)})

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!")

value

catch : (forall [a] {(m a) -> {e -> (m a)} -> (m a)})

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!")

datatype

(data (Error/T e m a)
  (Error/T (m (Either e a))))
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.

procedure

(run-error x)  (Either e a)

  x : (Error/T e Identity a)
Runs the error monad transformer computation x and extracts the possibly-aborted result.