Skip to content

Instantly share code, notes, and snippets.

@robrix
Created June 20, 2021 23:19
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 robrix/1f142b972e157a79e7a82e136d0cba29 to your computer and use it in GitHub Desktop.
Save robrix/1f142b972e157a79e7a82e136d0cba29 to your computer and use it in GitHub Desktop.
Least and greatest fixed-points in Haskell
newtype Mu f = Mu (forall r . (f r -> r) -> r)
foldMu :: (f a -> a) -> Mu f -> a
foldMu alg (Mu f) = f alg
unfoldMu :: Functor f => (a -> f a) -> a -> Mu f
unfoldMu coalg a = Mu $ \ alg -> refold alg coalg a
refoldMu :: Functor f => (f b -> b) -> (a -> f a) -> a -> b
refoldMu f g = foldMu f . unfoldMu g
mu :: Functor f => f (Mu f) -> Mu f
mu = unfoldMu (fmap getMu)
getMu :: Functor f => Mu f -> f (Mu f)
getMu = foldMu (fmap mu)
nuToMu :: Functor f => Nu f -> Mu f
nuToMu = unfoldMu getNu
data Nu f = forall r . Nu (r -> f r) r
unfoldNu :: (a -> f a) -> a -> Nu f
unfoldNu = Nu
foldNu :: Functor f => (f a -> a) -> Nu f -> a
foldNu alg (Nu coalg a) = refold alg coalg a
refoldNu :: Functor f => (f b -> b) -> (a -> f a) -> a -> b
refoldNu f g = foldNu f . unfoldNu g
nu :: Functor f => f (Nu f) -> Nu f
nu = unfoldNu (fmap getNu)
getNu :: Functor f => Nu f -> f (Nu f)
getNu = foldNu (fmap nu)
muToNu :: Functor f => Mu f -> Nu f
muToNu = unfoldNu getMu
refold :: Functor f => (f b -> b) -> (a -> f a) -> a -> b
refold f g = go where go = f . fmap go . g
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment