-
Notifications
You must be signed in to change notification settings - Fork 1
N_P3Ch08b_FalgFreeMonad
Markdown of literate Haskell program. Program source: /src/CTNotes/P3Ch08b_FalgFreeMonad.lhs
Notes about F-algerbas and the free monad. The book does not talk about Free but I decided to research it and I wrote this note about it.
Book Ref: CTFP P3 Ch8. F-Algebras.
Refs: Doel, schoolofhaskell
comonad reader
nlab free monad
module CTNotes.P3Ch08b_FalgFreeMonad where
import Control.Monad
Free functor (free monad):
data Free f a = Pure a | MkFree (f (Free f a))
instance Functor f => Functor (Free f) where
fmap fn (Pure a) = Pure (fn a)
fmap fn (MkFree expr) = MkFree (fmap fn <$> expr)
instance Functor f => Monad (Free f) where
return = Pure
Pure x >>= g = g x
MkFree f >>= g = MkFree $ (>>= g) <$> f
instance Functor f => Applicative (Free f) where
pure = return
(<*>) = ap
There is category Mnd where objects are monads and morphisms are natural transformations
that play nice with the monadic structure. This category can also be viewed as category of monoids in
monoidal category of endofunctors with composition.
Endo is standard category of endofunctors.
(See nlab free monad for more information.)
Forgetful functor:
U :: Mnd -> Endo
U (T, join, return) = T
Free functor
F :: Endo -> Mnd
F (Fx) = Free Fx
form an adjunction F -| U.
The adjunction says that monad morphisms (in Mnd) from Free F A
to some other monad M
correspond to
natural transformations from F
to M
. Natural transformations are used in implementing
interpreters for Free DSLs. TODO Is this a theoretical backing for that DSL approach?
Side note: As pointed out by the above comonad post
"The dual of substitution is redecoration"
(see also https://www.ioc.ee/~tarmo/papers/sfp01-book.pdf).
Think about fmap as substitution and join as renormalization.
m >>= f = join (fmap f m)
In Free
join is not renormalizing!
joinF :: Functor f => Free f (Free f a) -> Free f a
joinF (Pure a) = a
joinF (MkFree as) = MkFree (fmap joinF as)
"free monad is purely defined in terms of substitution".
End side note.
For a fixed functor f
, in pseudo-Haskell:
U:: F-Alg -> Hask
U (f, a, ev) = a
F:: Hask -> F-Alg
F a = (f, Free f a, MkFree)
Hom ((f, Free f a, MkFree), (f, b, evb) ~= a -> b
This adjunction viewed as isomorphism of homsets means that
each function a -> b
has a corresponding F-alg morphism from Free f a
to b
.
This is done by using evb
to collapse all layers in Free f.
type FAlgebra f a = f a -> a
Following method is the essential part of isomorphism in the reverse direction
iter :: Functor f => (f a -> a) -> Free f a -> a
iter _ (Pure a) = a
iter phi (MkFree m) = phi (iter phi <$> m)
iso1 :: Functor f => (a -> b) -> (f b -> b) -> Free f a -> b
iso1 a2b evb freefa = iter evb (fmap a2b freefa)
iso0 :: (Free f a -> b) -> a -> b
iso0 f = f . Pure
More about Free
The comonad post linked above continues as a 3 part sequel, N_P3Ch11a_KanExt has all of these posts linked.
This section is mostly a TODO.
Documentation in free
package has good short description of Cofree.
https://hackage.haskell.org/package/free-5/docs/Control-Comonad-Cofree.html
Cofree and Free work together well.
I have used it in my GraphPlay project.
(TODO find good writeup)
See http://blog.sigfpe.com/2014/05/cofree-meets-free.html