racket-algebraic
racket-algebraic copied to clipboard
Cannot define the writer monad
I tried to define the writer monad with an arbitrary monoid as the accumulator,
but could not figure out how to express the necessary class constraint.
The following program raises the error
writer.rkt:46:45: <>: no instance for semigroup
even though it should produce the value
(list (list "first" "third" "second" "fourth") 62)
.
Is this a limitation of the library or my own mistake?
#lang algebraic/racket/base
(require racket/match)
(require algebraic/control/applicative)
(require algebraic/control/monad)
(require algebraic/data/functor)
(require algebraic/data/list)
(require algebraic/data/monoid)
(require algebraic/data/semigroup)
(define (tell s)
(list s (void)))
(define (listen a)
(match a
((list s x) (list s (list s x)))))
(define (pass p)
(match p
((list s (list f x)) (list (f s) x))))
(define-syntax writer-functor
(instance functor
(fmap (lambda (f a)
(match a
((list s x) (list s (f x))))))))
(define-syntax writer-applicative
(instance applicative
extends (writer-functor)
(pure (lambda (x) (list mempty x)))
(<*> (lambda (p a)
(match p
((list s f) (match a
((list t x) (list (<> s t) (f x))))))))))
(define-syntax writer-monad
(instance monad
extends (writer-applicative)
(>>= (lambda (a k)
(match a
((list s x) (match (k x)
((list t y) (list (<> s t) y)))))))))
(with-instances (list-monoid writer-monad)
(>>= (pure 42) (lambda (x)
(>>M (tell (list "first"))
(>>= (pure 13) (lambda (y)
(>>= (pass (>>M (tell (list "second"))
(>>M (tell (list "third"))
(pure (list reverse 7))))) (lambda (z)
(>>M (tell (list "fourth"))
(pure (+ x y z)))))))))))