defmonad
, and provides ready to use implementations of some simple monads like Maybe. Support for the "do" notation (here called perform
) is included. assert-monad name
Checks whether a monad is defined, and signals an error if it's not
defmonad name user-return user->>=
Defines a new monad by specifying the name, the return and the bind (>>=) operations. For example, here's how the Maybe monad might be defined:
(define (just x) (list 'just x)) (define (nothing) (list 'nothing)) (define just? (t? 'just)) (define nothing? (t? 'nothing)) (defmonad 'maybe just (lambda (m1 f) (if (just? m1) (f (cadr m1)) m1)))And here's how we can use it (without the "do" notation):
(define *current-monad* 'maybe) ;Value: *current-monad* (>>= (just 50) (lambda (x) (return (* 2 x)))) ;Value 33: (just 100) (>> (nothing) (>>= (just 50) (lambda (x) (return (* 2 x))))) ;Value 34: (nothing)
just x
creates a "just" instance of the Maybe monad
nothing
creates a "nothing" instance of the Maybe monad
just? x
checks whether an object is a "just" instance of the maybe monad
nothing? x
checks whether an object is a "nothing" instance of the maybe monad
mapM monad-name func lst
The monadic equivalent of map
. Example:
(mapM 'maybe (lambda (x) (perform 'maybe (return (* 2 x)))) '(1 2 3 4)) ;Value 17: (just (2 4 6 8))
filterM monad-name pred lst
Monadic equivalent of filter
. Example:
(filterM 'maybe (lambda (x) (perform 'maybe (return (even? x)))) '(1 2 3 4 5 6 7 8)) ;Value 19: (just (2 4 6 8))
foldM monad-name func init lst
Monadic left fold (fold-left
). Example:
(foldM 'maybe (lambda (a b) (perform 'maybe (return (+ a b)))) 0 '(1 2 3 4 5)) ;Value 20: (just 15)
monad? monad-name
Checks whether a monad is defined. For example:
(monad? 'maybe) => #t
return x
the monadic return operator. Maps an underlying value to a monadic type. For example if *current-monad*
is set to 'maybe
:
(return 10) => (just 10)
>>= m1 f
the monadic bind operator. Example:
(define *current-monad* 'maybe) ;Value: *current-monad* (>>= (just 50) (lambda (x) (return (* 2 x)))) ;Value 33: (just 100)
>> m1 m2
like >>=
, but ignores the result. (>> (M x) (M y))
is equivalent to (>>= (M x) (lambda (x) (M y)))
perform monad {expressions}
Implements the "do" notation, which simplifies the monadic syntax. To bind monadic types to variables within a perform
, use mlet
.
Examples:
(define (safe-div a b) (if (eqv? b 0) (nothing) (just (/ a b)))) ;Value: safe-div (perform 'maybe (safe-div 10 5) (mlet ((x (safe-div 20 5)) (y (safe-div 30 5))) (return (* x y)))) ;Value 15: (just 24) (perform 'maybe (safe-div 10 5) (mlet ((x (safe-div 20 0)) ;division by zero! (y (safe-div 30 5))) (return (* x y)))) ;Value 16: (nothing)
mlet
Monadic let - for use with the "do" notation. See the example for the "perform" macro.
Scheme Power Tools Documentation
(c) Maciej Pacula 2010-2011
http://mpacula.com