2014-07-09 05:32:56 +00:00
|
|
|
(defmacro evaluate-m (monad mval)
|
|
|
|
`(cond ((: calrissian-util implements? 'state ,monad)
|
|
|
|
(call ,monad 'run ,mval 'undefined))
|
|
|
|
('true ,mval)))
|
|
|
|
|
|
|
|
(defmacro is-equal-m (monad mval1 mval2)
|
|
|
|
`(is-equal (evaluate-m ,monad ,mval1)
|
|
|
|
(evaluate-m ,monad ,mval2)))
|
|
|
|
|
2014-04-25 05:06:19 +00:00
|
|
|
(defmacro test-monad-functions (monad)
|
|
|
|
`(progn
|
|
|
|
(deftest monad->>=
|
2014-07-09 05:32:56 +00:00
|
|
|
(is-equal-m ,monad (return ,monad 2)
|
2014-04-25 05:06:19 +00:00
|
|
|
(>>= ,monad
|
|
|
|
(return ,monad 1)
|
|
|
|
(lambda (n) (return ,monad (+ 1 n))))))
|
|
|
|
(deftest monad->>
|
2014-07-09 05:32:56 +00:00
|
|
|
(is-equal-m ,monad (return ,monad 1)
|
2014-04-25 05:06:19 +00:00
|
|
|
(>> ,monad
|
|
|
|
(return ,monad 5)
|
|
|
|
(return ,monad 1))))
|
|
|
|
(deftest monad-do
|
2014-07-09 05:32:56 +00:00
|
|
|
(is-equal-m ,monad (return ,monad 'ok)
|
2014-04-25 05:11:04 +00:00
|
|
|
(do-m ,monad
|
|
|
|
(return ,monad 'ignored)
|
|
|
|
(return ,monad 'ok))))
|
2014-04-25 05:06:19 +00:00
|
|
|
(deftest monad-do-binding
|
2014-07-09 05:32:56 +00:00
|
|
|
(is-equal-m ,monad (return ,monad 9)
|
2014-04-25 05:11:04 +00:00
|
|
|
(do-m ,monad
|
|
|
|
(a <- (return ,monad 3))
|
|
|
|
(return ,monad (* a a)))))
|
2014-04-25 05:06:19 +00:00
|
|
|
(deftest monad-sequence
|
2014-07-09 05:32:56 +00:00
|
|
|
(is-equal-m ,monad (return ,monad (list 1 2 3))
|
2014-04-25 05:06:19 +00:00
|
|
|
(sequence ,monad (list (return ,monad 1)
|
|
|
|
(return ,monad 2)
|
|
|
|
(return ,monad 3)))))
|
|
|
|
))
|
|
|
|
|
2014-04-25 04:20:10 +00:00
|
|
|
(defmacro test-monad-laws (monad)
|
|
|
|
`(progn
|
|
|
|
(deftest monad-left-identity
|
|
|
|
(let ((a 3)
|
|
|
|
(f (lambda (n) (return ,monad (* 3 n)))))
|
2014-07-09 05:32:56 +00:00
|
|
|
(is-equal-m ,monad (>>= ,monad (return ,monad a) f)
|
2014-04-25 04:20:10 +00:00
|
|
|
(funcall f a))))
|
|
|
|
|
|
|
|
(deftest monad-right-identity
|
|
|
|
(let ((m (return ,monad 3)))
|
2014-07-09 05:32:56 +00:00
|
|
|
(is-equal-m ,monad (>>= ,monad m (lambda (m') (return ,monad m')))
|
2014-04-25 04:20:10 +00:00
|
|
|
m)))
|
|
|
|
|
|
|
|
(deftest monad-associativity
|
|
|
|
(let ((m (return ,monad 3))
|
|
|
|
(f (lambda (n) (return ,monad (* 3 n))))
|
|
|
|
(g (lambda (n) (return ,monad (+ 5 n)))))
|
2014-07-09 05:32:56 +00:00
|
|
|
(is-equal-m ,monad (>>= ,monad (>>= ,monad m f) g)
|
2014-04-25 04:20:10 +00:00
|
|
|
(>>= ,monad m (lambda (x) (>>= ,monad (funcall f x) g))))))
|
|
|
|
|
|
|
|
(deftest monad-do-left-identity
|
|
|
|
(let ((a 3)
|
|
|
|
(f (lambda (n) (return ,monad (* 3 n)))))
|
2014-07-09 05:32:56 +00:00
|
|
|
(is-equal-m ,monad (do-m ,monad (a' <- (return ,monad a))
|
2014-04-25 05:11:04 +00:00
|
|
|
(funcall f a'))
|
|
|
|
(do-m ,monad (funcall f a)))))
|
2014-04-25 04:20:10 +00:00
|
|
|
|
|
|
|
(deftest monad-do-right-identity
|
|
|
|
(let ((m (return ,monad 3)))
|
2014-07-09 05:32:56 +00:00
|
|
|
(is-equal-m ,monad (do-m ,monad (x <- m)
|
2014-04-25 05:11:04 +00:00
|
|
|
(return ,monad x))
|
|
|
|
(do-m ,monad m))))
|
2014-04-25 04:20:10 +00:00
|
|
|
|
|
|
|
(deftest monad-do-associativity
|
|
|
|
(let ((m (return ,monad 3))
|
|
|
|
(f (lambda (n) (return ,monad (* 3 n))))
|
|
|
|
(g (lambda (n) (return ,monad (+ 5 n)))))
|
2014-07-09 05:32:56 +00:00
|
|
|
(is-equal-m ,monad (do-m ,monad (y <- (do-m ,monad (x <- m)
|
2014-04-25 05:11:04 +00:00
|
|
|
(funcall f x)))
|
|
|
|
(funcall g y))
|
|
|
|
(do-m ,monad (x <- m)
|
|
|
|
(do-m ,monad (y <- (funcall f x))
|
|
|
|
(funcall g y))))))
|
2014-04-25 04:20:10 +00:00
|
|
|
))
|
2014-04-25 05:06:19 +00:00
|
|
|
|
|
|
|
(defmacro test-monad (monad)
|
|
|
|
`(progn
|
|
|
|
(test-monad-functions ,monad)
|
|
|
|
(test-monad-laws ,monad)))
|