{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
module Main where
import Data.Functor.Foldable
import Data.Functor.Foldable.TH
import Data.Functor.Identity
import Data.List (foldl')
import Language.Haskell.TH
import Test.HUnit
data Expr a
= Lit a
| Add (Expr a) (Expr a)
| Expr a :* [Expr a]
deriving (Show)
makeBaseFunctor ''Expr
data Expr2 a
= Lit2 a
| Add2 (Expr2 a) (Expr2 a)
deriving (Show)
makeBaseFunctorWith (runIdentity $ baseRulesCon (\_-> Identity $ mkName . (++ "'") . nameBase) baseRules
>>= baseRulesType (\_ -> Identity $ mkName . (++ "_") . nameBase)
) ''Expr2
expr1 :: Expr Int
expr1 = Add (Lit 2) (Lit 3 :* [Lit 4])
-- This is to test newtype derivation
--
-- Kind of a list
newtype L a = L { getL :: Maybe (a, L a) }
deriving (Show, Eq)
makeBaseFunctor ''L
cons :: a -> L a -> L a
cons x xs = L (Just (x, xs))
nil :: L a
nil = L Nothing
-- Test #33
data Tree a = Node {rootLabel :: a, subForest :: Forest a}
deriving (Show)
type Forest a = [Tree a]
makeBaseFunctor ''Tree
main :: IO ()
main = do
let expr2 = ana divCoalg 55 :: Expr Int
14 @=? cata evalAlg expr1
55 @=? cata evalAlg expr2
let lBar = cons 'b' $ cons 'a' $ cons 'r' nil
"bar" @=? cata lAlg lBar
lBar @=? ana lCoalg "bar"
let expr3 = Add2 (Lit2 21) $ Add2 (Lit2 11) (Lit2 10)
42 @=? cata evalAlg2 expr3
let expr4 = Node 5 [Node 6 [Node 7 []], Node 8 [Node 9 []]]
35 @=? cata treeAlg expr4
where
-- Type signatures to test name generation
evalAlg :: ExprF Int Int -> Int
evalAlg (LitF x) = x
evalAlg (AddF x y) = x + y
evalAlg (x :*$ y) = foldl' (*) x y
evalAlg2 :: Expr2_ Int Int -> Int
evalAlg2 (Lit2' x) = x
evalAlg2 (Add2' x y) = x + y
divCoalg x
| x < 5 = LitF x
| even x = 2 :*$ [x']
| otherwise = AddF x' (x - x')
where
x' = x `div` 2
lAlg (LF Nothing) = []
lAlg (LF (Just (x, xs))) = x : xs
lCoalg [] = LF { getLF = Nothing } -- to test field renamer
lCoalg (x : xs) = LF { getLF = Just (x, xs) }
treeAlg :: TreeF Int Int -> Int
treeAlg (NodeF r f) = r + sum f