Skip to content

Instantly share code, notes, and snippets.

@mgreenly
Last active August 29, 2015 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mgreenly/27bde37eeb3c17124ed9 to your computer and use it in GitHub Desktop.
Save mgreenly/27bde37eeb3c17124ed9 to your computer and use it in GitHub Desktop.
; monads
;
; references:
; http://onclojure.com/2009/03/05/a-monad-tutorial-for-clojure-programmers-part-1/
; http://www.intensivesystems.net/tutorials/monads_101.html
;
; define the 'identity' monad
;
(define-class <identity> ()
((value :init-keyword :value :accessor value-of)))
(define-method return (monad value)
(make monad :value value))
(define-method bind (monad function)
(return monad (function (ref monad 'value))))
(define-method just (monad)
(ref monad 'value))
;
; define a few functions to use on the monadic values
;
(define (f v) (* v v)) ; square the value
(define (g v) (+ v v)) ; double the value
; example
;
(just (bind (return <identity> 3) f)) ; -> 9
;
; explained
;
; The 'return' wraps the value 3 in an instance of the identity monad
;
; The 'bind' passes the function 'f' to the instance of the idenity monad
; created by return. The function f squares values passed to it.
;
; The 'just' unwraps the monadic result of the 'bind' to get it's value
; which is 9 in this case.
;
; notice that sequence is correctly preserved
;
(just (bind (bind (return <identity> 3) f) g)) ; -> 18
(just (bind (bind (return <identity> 3) g) f)) ; -> 36
; in the first case 3 is squared then doubled 3 -> 9 -> 18
; in the second csae 3 is doubled then squared 3 > 6 -> 36
; TODO
;
; create a 'sequence' macro so we can get rid of all the parens and just write...
;
(just (sequence <identity> 3 f g)) ; -> 18
(just (sequence <identity> 3 g f)) ; -> 36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment