module Data.Functor.Foldable.Examples (
Bert (..)
, Ernie (..)
, BertF (..)
, ErnieF (..)
, collapseErnieSyntaxTree
, collapseErnieSyntaxTree'
, collapseBertSyntaxTree
, collapseBertSyntaxTree'
) where
import Control.DeepSeq (NFData)
import Data.Functor.Foldable
import Data.Functor.Foldable.Exotic
import Data.Functor.Foldable.TH
import GHC.Generics (Generic)
data Bert = Bert Ernie
| Num Integer
| String String
| Add Bert Bert
deriving (Show, Eq, Generic, NFData)
data Ernie = Ernie Bert
| Multiply Ernie Ernie
| List [Ernie]
deriving (Show, Eq, Generic, NFData)
makeBaseFunctor ''Ernie
makeBaseFunctor ''Bert
bertAlgebra :: BertF Bert -> Bert
bertAlgebra (AddF (Num i) (Num j)) = Num $ i + j
bertAlgebra x = embed x
ernieAlgebra :: ErnieF Ernie -> Ernie
ernieAlgebra (MultiplyF (Ernie (Num i)) (Ernie (Num j))) = Ernie . Num $ i * j
ernieAlgebra x = embed x
collapseErnieSyntaxTree :: (Recursive Ernie, Recursive Bert) => Ernie -> Ernie
collapseErnieSyntaxTree = dendro undefined bertAlgebra ernieAlgebra
collapseBertSyntaxTree :: (Recursive Bert, Recursive Ernie) => Bert -> Bert
collapseBertSyntaxTree = dendro undefined ernieAlgebra bertAlgebra
collapseErnieSyntaxTree' :: (Recursive Ernie) => Ernie -> Ernie
collapseErnieSyntaxTree' = cata algebra
where algebra (ErnieF e) = Ernie $ collapseBertSyntaxTree' e
algebra (MultiplyF (Ernie (Num i)) (Ernie (Num j))) = Ernie . Num $ i * j
algebra x = embed x
collapseBertSyntaxTree' :: (Recursive Bert) => Bert -> Bert
collapseBertSyntaxTree' = cata algebra
where algebra (BertF e) = Bert $ collapseErnieSyntaxTree' e
algebra (AddF (Num i) (Num j)) = Num $ i + j
algebra x = embed x