Skip to content

Latest commit

 

History

History
40 lines (32 loc) · 1.36 KB

File metadata and controls

40 lines (32 loc) · 1.36 KB

How Do I Convert Between (Co)Recursive Structures?

https://gitter.im/slamdata/matryoshka?at=5b5742a2c86c4f0b472f38c0

When you’re transforming data between two recursive structures, your best bet is to define a natural transformation rather than using an Algebra or Coalgebra directly.

-- ideally
myNat :: forall a. f a -> g a
-- so now you can
cata (embed <<< myNat)
-- or
ana (myNat <<< project)
-- the former can give you a finite structure (but only if you’ve started with
-- one) and the later can take any structure, but will result in a potentially-
-- infinite one. So rather than defining both a `Algebra` and a `Coalgebra` for
-- the various cases, you have one natural transformation for whichever you
-- need.

-- But there’s also magical fusion …
myGAlg :: Algebra g b

myFFold :: Mu f -> b
myFFold cata myAlg <<< cata (embed <<< myNat)

myFFold' :: Mu f -> b
myFFold' = cata (myGAlg <<< myNat)
-- natural transformations compose very nicely with whatever other (co)algebras
-- you may have, eliminating ever constructing a value of `Mu g` along the way.
-- however, sometimes your `f` can result in multiple `g`s
myNatOrMore :: forall a. f a -> g (Free g a)
-- and sometimes zero `g`s
myNatMoreOrLess :: forall a. f a -> Free g a

-- The Free cases are _mostly_ a bit trickier, except for
gana distFree (myNatOrMore <<< project)