Created
May 7, 2014 01:50
-
-
Save mgreenly/808e8fb744cb59d76668 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; monads | |
; | |
; references: | |
; http://onclojure.com/2009/03/05/a-monad-tutorial-for-clojure-programmers-part-1/ | |
; http://www.intensivesystems.net/tutorials/monads_101.html | |
; http://en.wikipedia.org/wiki/Monad_(functional_programming) | |
; http://moonbase.rydia.net/mental/writings/programming/monads-in-ruby/00introduction.html | |
; alternate syntax for make monad | |
(define-syntax return | |
(syntax-rules () | |
((return m v) | |
(make m :value v)) | |
((return m) | |
(make m)))) | |
; alternate syntax for bind | |
(define-syntax >>= | |
(syntax-rules () | |
((>>= function monad) | |
(bind function monad)))) | |
; | |
; NOTHING | |
; | |
(define-class <nothing> () ()) | |
(define-method value-of ((_ <nothing>)) 'nothing) | |
(define-method bind (function (monad <nothing>)) | |
(return <nothing>)) | |
(define nothing (return <nothing>)) | |
; | |
; MAYBE | |
; | |
(define-class <maybe> () | |
((value :init-keyword :value :accessor value-of))) | |
(define-method bind (function (monad <maybe>)) | |
(let ((result (function (value-of monad)))) | |
(if result | |
(return <maybe> result) | |
nothing))) | |
(define (f n) (+ n n)) | |
(define (g n) (* n n)) | |
(define (h n) (if (> n 10) #f n)) | |
; | |
(f (g (h 3))) ; -> 18 | |
((compose f g h) 3) ; -> 18 | |
(bind f (bind g (bind h (return <maybe> 3)))) ; -> <maybe> 18 | |
; | |
; bind composes functions that expect basic values so that they | |
; work with monadic values and returns the result as a monadic | |
; value so it's ready for the next bind in the chain. | |
; | |
; Monadic Parser | |
; This is PEG grammar (find references) | |
;seq takes a series of rules and expects each in order. If any rule | |
;fails the seq fails. This is essentially the maybe monad. It would | |
;be defined as syntax and look like this | |
(define (digits stream) | |
(seq stream | |
(digit | |
digit))) | |
;the seq syntax would expand into to someting like this | |
(define (digits stream) | |
(bind digit (bind digit stream))) | |
;takes n rules and returns the result of the first rule that does not return | |
;false. if they all return false it returns false. | |
(define (sel stream . rules) | |
rules) | |
;returns zero or more of rule | |
(define (rep* stream . rule) | |
rule) | |
;returns one or more of rule | |
(define (rep+ stream . rule) | |
rule) | |
;returns zero or one of rule | |
(define (rep? stream . rule) | |
rule) | |
;returns rule if pred follows it. does not consume pred | |
(define (and? stream rule pred) | |
(rule)) | |
;returns rule if pred does not follow it. does not consume pred | |
(define (not? stream rule pred) | |
(rule))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment