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

2.5 Monad Transformers

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

typeclass

(class (MonadTrans 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 Reader

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

datatype

(data (ReaderT r m a)
  (ReaderT {r -> (m a)}))
The reader monad transformer, a monad transformer that extends a monad with a read-only dynamic environment. The environment can be accessed with ask and locally modified with local.

> (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 : (ReaderT 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 : (ReaderT r Identity a)
  ctx : r
Runs the reader monad transformer computation x with the context ctx and extracts the result.

value

ask : (forall [r m] (ReaderT r 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"

procedure

(asks f)  (ReaderT r m a)

  f : {r -> 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)

procedure

(local f x)  (ReaderT r m a)

  f : {r -> r}
  x : (ReaderT r m a)
Produces a computation like x, except that the environment is modified in its dynamic extent by applying f to it.

2.5.2 Error

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

datatype

(data (ErrorT e m a)
  (ErrorT (m (Either e a))))
The error monad transformer, a monad transformer that extends a monad with a notion of failure. Failures short-circuit other computations in the monad, and they can carry information, usually information about what caused the 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 : (ErrorT 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 : (ErrorT e Identity a)
Runs the error monad transformer computation x and extracts the possibly-aborted result.

procedure

(throw ex)  (ErrorT e m a)

  ex : e
Produces a computation that raises ex 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!")

procedure

(catch x handler)  (ErrorT e* m a)

  x : (ErrorT e m a)
  handler : {e -> (ErrorT e* m a)}
Produces a computation like x, except any errors raised are handled via handler 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 Unit String))

: (Either Unit String)

(Right "Caught error: Ack!")