Skip to content

Instantly share code, notes, and snippets.

@gatlin
Last active August 29, 2015 14:26
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 gatlin/6b4253a75df1acf866f9 to your computer and use it in GitHub Desktop.
Save gatlin/6b4253a75df1acf866f9 to your computer and use it in GitHub Desktop.
#lang racket
; We begin with the S and K combinators
(define S (λ (x)
(λ (y)
(λ (z)
((x z) (y z))))))
(define K (λ (x) (λ (y) x)))
; The I combinator falls out pretty easily from these two, giving an identity function
(define I ((S K) K)) ; (I 2) => 2
; Function composition is also easily defined with these combinators
(define compose ((S (K S)) K))
; reverse function application, which we will use momentarily
(define app ((S (K (S I))) K)) ; (app x f) => (f x)
; We have everything we need to define the monad over unary functions
; (in Haskell it's called the `Reader` monad).
; This monad allows computations to thread a read-only state value through
; composition of functions.
(define return K)
(define join (S app))
(define (>>= ma f) (join ((compose f) ma)))
; `ask` is how a computation may access the state value.
(define ask I)
; `local` may be used to modify the state value locally for a sub-computation, though
; it will be reverted when the sub-computation terminates.
(define (local f m) ((compose m) f))
(define r1
(ask . >>= . (λ (n)
(return (eq? (modulo n 2) 0)))))
(define r2 (λ (is-even?)
(ask . >>= . (λ (n)
(let ([s (number->string n)])
(if is-even?
(return (string-append s " is even!"))
(return (string-append s " is odd!"))))))))
(define r3 (r1 . >>= . r2))
(define plus-1 (λ (x) (+ 1 x)))
(define r4
(ask . >>= . (λ (n)
(local plus-1 r1))))
(define r5 (r4 . >>= . r2))
; (r1 10) => #t
; (r3 10) => "10 is even!"
; (r5 10) => "10 is odd!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment