-
Notifications
You must be signed in to change notification settings - Fork 0
/
AEZipper.hs
89 lines (68 loc) · 2.12 KB
/
AEZipper.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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
module AEZipper (
Crumb (LExpr, RExpr, DPara),
AEZipper,
zipper,
snag,
zipLeft,
zipRight,
zipDown,
zipUp,
zipTop,
zInsert,
compose,
(-:),
(.>)
) where
import AExpr
data Crumb a =
LExpr Oper (AExpr a) |
RExpr Oper (AExpr a) |
DPara deriving (Show, Eq)
data AEZipper a = Zipper ((AExpr a), [Crumb a]) | Snag deriving (Show, Eq)
instance Functor Crumb where
fmap f (LExpr o e) = LExpr o (f <$> e)
fmap f (RExpr o e) = RExpr o (f <$> e)
fmap f (DPara) = DPara
instance Functor AEZipper where
fmap f (Zipper (e, cs)) = Zipper (f <$> e, (f <$>) <$> cs)
fmap f Snag = Snag
zipper :: (AExpr a) -> AEZipper a
zipper e = Zipper (e, [])
snag :: AEZipper a
snag = Snag
-- Make composing Zipper functions look neater
(-:) :: AEZipper a -> (AEZipper a -> AEZipper b) -> AEZipper b
zipper -: fs = fs zipper
-- Build a composite function from a list
compose [] = id
compose (f:fs) = f .> (compose fs)
-- Left-associative composition operator
(.>) :: (a -> b) -> (b -> c) -> a -> c
f .> g = g.f
-- Move left, right, down, up and to the top of the tree
zipLeft :: AEZipper a -> AEZipper a
zipLeft Snag = Snag
zipLeft (Zipper (Expr o l r, bs)) = Zipper (l, (LExpr o r):bs)
zipLeft (Zipper (_, bs)) = Snag
zipRight :: AEZipper a -> AEZipper a
zipRight Snag = Snag
zipRight (Zipper (Expr o l r, bs)) = Zipper (r, (RExpr o l):bs)
zipRight (Zipper (_, bs)) = Snag
zipDown :: AEZipper a -> AEZipper a
zipDown Snag = Snag
zipDown (Zipper (Para e, bs)) = Zipper (e, DPara:bs)
zipDown (Zipper (_, bs)) = Snag
zipUp :: AEZipper a -> AEZipper a
zipUp Snag = Snag
zipUp (Zipper (e, [])) = Snag
zipUp (Zipper (e, (LExpr o r):bs)) = Zipper (Expr o e r, bs)
zipUp (Zipper (e, (RExpr o l):bs)) = Zipper (Expr o l e, bs)
zipUp (Zipper (e, DPara:bs)) = Zipper (Para e, bs)
zipTop :: AEZipper a -> AEZipper a
zipTop Snag = Snag
zipTop (Zipper (e, [])) = Zipper (e, [])
zipTop (Zipper (e, cs)) = zipTop $ zipUp (Zipper (e, cs))
-- Manipulate the part of the tree under focus
zInsert :: AExpr a -> AEZipper a -> AEZipper a
zInsert _ Snag = Snag
zInsert e (Zipper (_, cs)) = Zipper (e, cs)