(std monad)

Reference

Overview

The Monad trait, instances for List, Option, and Result, and do-notation.

(import (std prelude))
(import (std monad))

(: calc (-> int (Option int)))
(defun (calc n)
  (do (:bind half (safe-div n 2))
      (:let  doubled (* half 2))
      (:bind third (safe-div doubled 3))
      (:return (+ doubled third))))

A monad is a type constructor that supports two core operations: pure lifts a regular value into the monad, and bind sequences computations by passing an inner value to a function returning the next monad. The (do ...) macro provides convenient sequential step syntax over chained bind calls.

Standard instances.

The return type of the block determines which instance is used.

See also: pure, bind, do

Reference

Types

Functions

Macros

Types

Monad

trait ↑ Types

Trait for sequencing monadic computations via pure and bind.

Requires implementing pure and bind for a type constructor (such as List or Option), enabling (do ...) syntax for that type.

See also: pure, bind, do

Functions

pure

function ↑ Functions

(: pure (-> %a (%m %a)))

Lifts a value into a monadic context.

x
The value to wrap.
returns
A monad wrapping x: (Cons x Nil), (Some x), or (Ok x).

See also: bind, do

bind

function ↑ Functions

(: bind (-> (%m %a) (-?-> %a (%m %b)) (%m %b)))

Sequences monadic computations by applying a function to the contained value.

m
The monadic value.
k
Continuation function taking an inner value and returning a monad. May be a fun or bjoroutine.
returns
The resulting monad from k. For List, concatenates all results in order. For None or Err, returns m unchanged without calling k.
(bind (Some 2) (fun (x) (Some (* x 10))))   ; (Some 20)
(bind (list 1 2) (fun (x) (list x x)))      ; (1 1 2 2)

See also: pure, do

Macros

do

macro ↑ Macros

(do step ...)

Sequences monadic operations using step-based do-notation.

step ...

A step, one of:

(:bind name expr): binds name to the unwrapped value of monad expr. name must be an identifier.

(:match pattern expr): like :bind, but destructures the unwrapped value against pattern. Mismatches raise an exception.

(:let name expr): binds name directly to expr without monadic unwrapping.

(:then expr): evaluates the monad expr for side effects and discards its inner value.

(:return expr): valid in final step position only. Returns (pure expr).

Any other expression: evaluated for side effects without unwrapping. In the final position, it determines the block's return value and must evaluate to a monad.

;; All sums of pairs from two lists.
(do (:bind x (list 1 2))
    (:bind y (list 10 20))
    (:return (+ x y)))          ; (11 21 12 22)

;; Stops at the first Err.
(do (:match (Tuple w h) (parse-pair text))
    (:bind width (checked w))
    (:bind height (checked h))
    (:return (* width height)))

The block requires at least one step. The final step defines the block’s result: either an explicit :return or an expression returning a monad. Binding steps (:bind, :match, :let, or :then) cannot appear in the final position. Unrecognized keywords in step position produce syntax errors.

The final step can be a recursive call returning a monad, allowing tail calls in monadic loops.

Steps following :bind, :match, or :then compile into the body of a lambda passed to bind, and therefore cannot suspend.

See also: bind, pure