-
Notifications
You must be signed in to change notification settings - Fork 0
/
mhCata.hs
54 lines (39 loc) · 1.25 KB
/
mhCata.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
{-# LANGUAGE LambdaCase #-}
-- Meijer/Hutton catamorphism/anamorphism for datatypes; adapted from Boxes go bananas
newtype Value =
Fn (Value -> Value)
unFn (Fn x) = x
newtype Rec a =
Roll (a (Rec a)) -- recursion
data ExpF a -- terms are either lam expressions or function applications
= Lam (a -> a)
| App a a
type Exp = Rec ExpF
lam :: (Exp -> Exp) -> Exp -- lambda expression
lam x = Roll (Lam x)
app :: Exp -> Exp -> Exp -- function applications
app x y = Roll (App x y)
xmapExpF :: (a -> b, b -> a) -> (ExpF a -> ExpF b, ExpF b -> ExpF a)
xmapExpF (f, g) =
( \case
Lam x -> Lam (f . x . g)
App y z -> App (f y) (f z)
, \case
Lam x -> Lam (g . x . f)
App y z -> App (g y) (g z))
cata :: (ExpF a -> a) -> (a -> ExpF a) -> Rec ExpF -> a -- catamorphism
cata f g (Roll x) = f (fst (xmapExpF (cata f g, ana f g)) x)
ana :: (ExpF a -> a) -> (a -> ExpF a) -> a -> Rec ExpF
ana f g x = Roll (snd (xmapExpF (cata f g, ana f g)) (g x))
evalAux :: ExpF Value -> Value
evalAux (Lam f) = Fn f
evalAux (App x y) = unFn x y
unevalAux :: Value -> ExpF Value
unevalAux (Fn f) = Lam f
eval :: Exp -> Value
eval = cata evalAux unevalAux
-- Example expressions
identity :: Exp
identity = lam id
idAppid :: Exp
idAppid = app identity identity