git.iko.soy/rowtype-yoga/purescript-yoga-tree
on master help sign in
Changed to a Cofree based Tree type.
commit285046ece32cdf9c031496859d0183eb55993548 authorDaniel Fortes <daniel.mbfm@gmail.com> dateFri 8 Sep 2017, 22:49 (9 years ago) parent2acc1a0
4 files changed+120−172
bower.json+2−1 src/Data/Tree.purs+24−81 src/Data/Tree/Zipper.purs+27−23 test/Main.purs+67−67
bower.json+2−1
@@ -14,7 +14,8 @@
1414 "dependencies": {
1515 "purescript-prelude": "^3.1.0",
1616 "purescript-console": "^3.0.0",
17− "purescript-lists": "^4.9.1"
17+ "purescript-lists": "^4.9.1",
18+ "purescript-free": "^4.1.0"
1819 },
1920 "devDependencies": {
2021 "purescript-psci-support": "^3.0.0",
src/Data/Tree.purs+24−81
@@ -2,81 +2,31 @@ module Data.Tree where
22
33import Prelude
44
5−import Control.Apply (lift2)
5+import Control.Comonad.Cofree (Cofree, head, mkCofree, tail, (:<))
66import Control.Monad.Rec.Class (Step(..), tailRec)
7−import Data.Foldable (class Foldable, foldMap, foldlDefault, foldrDefault)
8−import Data.Generic (class Generic, gEq, gShow)
7+import Data.Generic (class Generic)
98import Data.List (List(..), snoc, (:))
109import Data.Monoid (power)
11−import Data.Traversable (class Traversable, Accum, sequenceDefault, traverse)
10+import Data.Traversable (Accum)
1211
1312-- | A Rose, or multi-way tree, with values of type `a`.
14−newtype Tree a = Node { value :: a
15− , children :: Forest a
16− }
13+type Tree a = Cofree List a
1714
18−-- | A `Forest` is a list of `Tree`s.
1915type Forest a = List (Tree a)
2016
2117-- | Create a `Tree` from a `Node` value of type `a` and a `Forest` of children.
2218mkTree :: forall a. a -> Forest a -> Tree a
23−mkTree a cs = Node { value: a, children: cs }
24−
25−infix 5 mkTree as |>
26−
27−-- Instances
28−
29−derive instance genericTree :: Generic a => Generic (Tree a)
30−
31−instance eqTree :: Generic a => Eq (Tree a) where
32− eq = gEq
33−
34−instance showTree' :: Generic a => Show (Tree a) where
35− show = gShow
36−
37−instance functorTree :: Functor Tree where
38− map f (Node {value:v, children: c}) = mkTree (f v) (tailRec go {current: c, result: Nil})
39− where
40− go {current: Nil, result: r} = Done r
41− go {current: c:cs, result: r} =
42− Loop {current: cs, result: snoc r (mkTree (f (nodeValue c)) (tailRec go {current: (nodeChildren c), result: Nil })) }
43−
44−instance applyTree :: Apply Tree where
45− apply (Node {value: f, children: fs}) tx@(Node {value: x, children: xs})
46− = Node {value: (f x), children: ((map <<< map) f xs) <> (map ((flip apply) tx) fs)}
47−
48−instance applicativeTree :: Applicative Tree where
49− pure = (flip $ mkTree) Nil
50−
51−instance bindTree :: Bind Tree where
52− bind tx@(Node {value: x, children: xs}) f =
53− let (Node {value: b, children: bs}) = f x in
54− Node {value: b, children: bs <> (map ((flip bind) f) xs)}
55−
56−instance monadTree :: Monad Tree
57−
58−instance foldableTree :: Foldable Tree where
59− foldMap f (Node {value: x, children: xs}) = (f x) <> (foldMap (foldMap f) xs)
60− foldl f = foldlDefault f
61− foldr f = foldrDefault f
62−
63−instance traversableTree :: Traversable Tree where
64− traverse f (Node {value: x, children: xs}) =
65− lift2 (\a b -> Node {value: a, children: b}) (f x) (traverse (traverse f) xs)
66−
67− sequence x = sequenceDefault x
68−
69−-- Other functions
19+mkTree = mkCofree
7020
7121-- | Draw a 2D `String` representation of a `Tree String`.
7222drawTree :: Tree String -> String
73−drawTree t = tailRec go {level: 0, drawn: (nodeValue t) <> "\n", current: (nodeChildren t)}
23+drawTree t = tailRec go {level: 0, drawn: (head t) <> "\n", current: (tail t)}
7424 where
7525 go :: _ -> Step _ String
7626 go {level: l, drawn: s, current: Nil} = Done s
7727 go {level: l, drawn: s, current: c:cs } =
78− let drawn = (power " " l) <> "|----> " <> (nodeValue c) <> "\n" in
79− Loop {level: l, drawn: s <> drawn <> (tailRec go {level: l + 1, drawn: "", current: (nodeChildren c)}) , current: cs}
28+ let drawn = (power " " l) <> "|----> " <> (head c) <> "\n" in
29+ Loop {level: l, drawn: s <> drawn <> (tailRec go {level: l + 1, drawn: "", current: (tail c)}) , current: cs}
8030
8131-- | Draw a 2D `String` representation of a `Tree` composed of `Show`able
8232-- | elements.
@@ -86,44 +36,37 @@ showTree = drawTree <<< (map show)
8636-- | Scan a `Tree`, accumulating values of `b` there are constant across `Node`s
8737-- | that have the same parent.
8838scanTree :: forall a b. (a -> b -> b) -> b -> Tree a -> Tree b
89−scanTree f b n@(Node {value: x, children: xs}) =
90− let fb = f x b
91− in fb |> (tailRec go {b: fb, current: xs, final: Nil})
39+scanTree f b n =
40+ let fb = f (head n) b
41+ in fb :< (tailRec go {b: fb, current: (tail n), final: Nil})
9242 where
9343 go :: _ -> Step _ (Forest b)
9444 go {b: b', current: Nil, final: final} = Done final
9545 go {b: b', current: c:cs, final: final} =
96− let fb' = f (nodeValue c) b'
97− in Loop {b: b', current: cs, final: snoc final (fb' |> tailRec go {b: fb', current: (nodeChildren c), final: Nil})}
46+ let fb' = f (head c) b'
47+ in Loop {b: b', current: cs, final: snoc final (fb' :< tailRec go {b: fb', current: (tail c), final: Nil})}
9848
9949-- | Scan a `Tree`, accumulating values of `b` there are constant across `Node`s
10050-- | that have the same parent, and returning a `Tree` of type `c`.
10151scanTreeAccum :: forall a b c. (a -> b -> Accum b c) -> b -> Tree a -> Tree c
102−scanTreeAccum f b n@(Node {value: x, children: xs}) =
103− let fb = f x b
104− in fb.value |> (tailRec go {b: fb.accum , current: xs, final: Nil})
52+scanTreeAccum f b n =
53+ let fb = f (head n) b
54+ in fb.value :< (tailRec go {b: fb.accum , current: (tail n), final: Nil})
10555 where
10656 go :: _ -> Step _ (Forest c)
10757 go {b: b', current: Nil, final: final} = Done final
10858 go {b: b', current: c:cs, final: final} =
109− let fb' = f (nodeValue c) b'
110− in Loop {b: b', current: cs, final: snoc final (fb'.value |> tailRec go {b: fb'.accum, current: (nodeChildren c), final: Nil})}
111−
112−-- Setters and getters
113−nodeValue :: forall a. Tree a -> a
114−nodeValue (Node r) = r.value
115−
116−nodeChildren :: forall a. Tree a -> Forest a
117−nodeChildren (Node r) = r.children
59+ let fb' = f (head c) b'
60+ in Loop {b: b', current: cs, final: snoc final (fb'.value :< tailRec go {b: fb'.accum, current: (tail c), final: Nil})}
11861
62+-- | Set the value of a node.
11963setNodeValue :: forall a. a -> Tree a -> Tree a
120−setNodeValue a (Node r) = Node r { value = a }
64+setNodeValue a n = a :< (tail n)
12165
66+-- | Modify the value of a node.
12267modifyNodeValue :: forall a. (a -> a) -> Tree a -> Tree a
123−modifyNodeValue f (Node r) = Node r { value = f r.value }
68+modifyNodeValue f n = f (head n) :< tail n
12469
70+-- | Append a child to a node.
12571appendChild :: forall a. Tree a -> Tree a -> Tree a
126−appendChild n (Node r) = Node r { children = snoc r.children n }
127−
128−setChildren :: forall a. Forest a -> Tree a -> Tree a
129−setChildren cs (Node r) = Node r { children = cs }
72+appendChild c n = head n :< snoc (tail n) c
src/Data/Tree/Zipper.purs+27−23
@@ -2,10 +2,16 @@ module Data.Tree.Zipper where
22
33import Prelude
44
5+import Control.Comonad.Cofree (head, tail, (:<))
56import Data.Generic (class Generic, gEq, gShow)
67import Data.List (List(..), drop, reverse, take, (!!), (:))
78import Data.Maybe (Maybe(..))
8−import Data.Tree (Forest, Tree(..), mkTree, modifyNodeValue, nodeChildren, nodeValue, setNodeValue)
9+import Data.Tree (Forest, Tree, mkTree, modifyNodeValue, setNodeValue)
10+
11+-- import Data.Generic (class Generic, gEq, gShow)
12+-- import Data.List (List(..), drop, reverse, take, (!!), (:))
13+-- import Data.Maybe (Maybe(..))
14+-- import Data.Tree (Forest, Tree(..), mkTree, modifyNodeValue, nodeChildren, nodeValue, setNodeValue)
915
1016-- | The `Loc` type describes the location of a `Node` inside a `Tree`. For this
1117-- | we store the current `Node`, the sibling nodes that appear before the current
@@ -22,16 +28,14 @@ newtype Loc a = Loc { node :: Tree a
2228 , parents :: List (Loc a)
2329 }
2430
31+instance eqLoc :: Eq a => Eq (Loc a) where
32+ eq (Loc r1) (Loc r2) =
33+ r1.node == r2.node
34+ && r1.before == r2.before
35+ && r1.after == r2.after
36+ && r1.parents == r2.parents
2537
26−derive instance genericLoc :: Generic a => Generic (Loc a)
27−
28−instance showLoc :: Generic a => Show (Loc a) where
29− show = gShow
30−
31−instance eqLoc :: Generic a => Eq (Loc a) where
32− eq = gEq
33−
34−-- Cursor movement
38+-- -- Cursor movement
3539
3640-- | Move the cursor to the next sibling.
3741next :: forall a. Loc a -> Maybe (Loc a)
@@ -44,7 +48,7 @@ next (Loc r) =
4448 , parents: r.parents
4549 }
4650
47−-- | Move the cursor to the previous sibling.
51+-- -- | Move the cursor to the previous sibling.
4852prev :: forall a. Loc a -> Maybe (Loc a)
4953prev (Loc r) =
5054 case r.before of
@@ -55,7 +59,7 @@ prev (Loc r) =
5559 , parents: r.parents
5660 }
5761
58−-- | Move the cursor to the first sibling.
62+-- -- | Move the cursor to the first sibling.
5963first :: forall a. Loc a -> Loc a
6064first l@(Loc r) =
6165 case r.before of
@@ -66,7 +70,7 @@ first l@(Loc r) =
6670 , parents: r.parents
6771 }
6872
69−-- | Move the cursor to the last sibling.
73+-- -- | Move the cursor to the last sibling.
7074last :: forall a. Loc a -> Loc a
7175last l@(Loc r) =
7276 case reverse r.after of
@@ -77,12 +81,12 @@ last l@(Loc r) =
7781 , parents: r.parents
7882 }
7983
80−-- | Move the cursor to the parent `Node`.
84+-- -- | Move the cursor to the parent `Node`.
8185up :: forall a. Loc a -> Maybe (Loc a)
8286up l@(Loc r) =
8387 case r.parents of
8488 Nil -> Nothing
85− (p:ps) -> Just $ Loc { node: mkTree (value p) (siblings l)
89+ (p:ps) -> Just $ Loc { node: (value p) :< (siblings l)
8690 , before: before p
8791 , after: after p
8892 , parents: ps
@@ -97,14 +101,14 @@ root l =
97101
98102-- | Move the cursor to the first child of the current `Node`.
99103firstChild :: forall a. Loc a -> Maybe (Loc a)
100−firstChild p@(Loc r) =
101− case r.node of
102− Node { value: _, children: Nil } -> Nothing
103− Node { value: _, children: c:cs } ->
104+firstChild n =
105+ case children n of
106+ Nil -> Nothing
107+ c:cs ->
104108 Just $ Loc { node: c
105109 , before: Nil
106110 , after: cs
107− , parents: p : r.parents
111+ , parents: n : (parents n)
108112 }
109113
110114-- | Move the cursor to the first child of the current `Node`.
@@ -174,7 +178,7 @@ setValue a l = setNode (setNodeValue a (node l)) l
174178modifyValue :: forall a. (a -> a) -> Loc a -> Loc a
175179modifyValue f l = setNode (modifyNodeValue f (node l)) l
176180
177−-- insert and delete nodes
181+-- -- insert and delete nodes
178182
179183-- | Insert a node after the current position, and move cursor to the new node.
180184insertAfter :: forall a. Tree a -> Loc a -> Loc a
@@ -267,7 +271,7 @@ node :: forall a. Loc a -> Tree a
267271node (Loc r) = r.node
268272
269273value :: forall a. Loc a -> a
270−value = nodeValue <<< node
274+value = head <<< node
271275
272276before :: forall a. Loc a -> Forest a
273277before (Loc r) = r.before
@@ -279,7 +283,7 @@ parents :: forall a. Loc a -> List (Loc a)
279283parents (Loc r) = r.parents
280284
281285children :: forall a. Loc a -> Forest a
282−children = nodeChildren <<< node
286+children = tail <<< node
283287
284288siblings :: forall a. Loc a -> Forest a
285289siblings (Loc r) = (reverse r.before) <> (r.node : r.after)
test/Main.purs+67−67
@@ -2,13 +2,13 @@ module Test.Main where
22
33import Prelude
44
5+import Control.Comonad.Cofree (Cofree, head, (:<))
56import Control.Monad.Eff (Eff)
67import Control.Monad.Eff.Class (liftEff)
78import Control.Monad.Eff.Console (CONSOLE, log)
89import Data.List (List(..), (:))
9−import Data.List.Partial (head)
1010import Data.Maybe (fromJust)
11−import Data.Tree (Tree, mkTree, nodeChildren, nodeValue, scanTree, showTree, (|>))
11+import Data.Tree (Tree, mkTree, scanTree, showTree)
1212import Data.Tree.Zipper (down, fromTree, insertAfter, modifyValue, next, toTree)
1313import Partial.Unsafe (unsafePartial)
1414import Test.Spec (describe, it)
@@ -18,14 +18,14 @@ import Test.Spec.Runner (RunnerEffects, run)
1818
1919sampleTree :: Tree Int
2020sampleTree =
21− 1 |>
22− (2 |> Nil)
23− : (3 |> Nil)
24− : (4 |>
25− (5 |> Nil)
26− : (6 |>
27− (7 |> Nil) : Nil)
28− : (8 |> Nil)
21+ 1 :<
22+ (2 :< Nil)
23+ : (3 :< Nil)
24+ : (4 :<
25+ (5 :< Nil)
26+ : (6 :<
27+ (7 :< Nil) : Nil)
28+ : (8 :< Nil)
2929 : Nil
3030 )
3131 : Nil
@@ -36,37 +36,37 @@ main = run [consoleReporter] do
3636
3737 it "mkTree" do
3838 let t = mkTree 10 Nil
39− shouldEqual (nodeValue t) 10
39+ shouldEqual (head t) 10
4040
4141 it "Functor" do
4242 let result =
43− 2 |>
44− (3 |> Nil)
45− : (4 |> Nil)
46− : (5 |>
47− (6 |> Nil)
48− : (7 |>
49− (8 |> Nil) : Nil)
50− : (9 |> Nil)
43+ 2 :<
44+ (3 :< Nil)
45+ : (4 :< Nil)
46+ : (5 :<
47+ (6 :< Nil)
48+ : (7 :<
49+ (8 :< Nil) : Nil)
50+ : (9 :< Nil)
5151 : Nil
5252 )
5353 : Nil
54− shouldEqual (((+)1) <$> sampleTree) result
54+ shouldEqual (eq (((+)1) <$> sampleTree) result) true
5555
5656 it "scanTree" do
5757 let result =
58− 1 |>
59− (3 |> Nil)
60− : (4 |> Nil)
61− : (5 |>
62− (10 |> Nil)
63− : (11 |>
64− (18 |> Nil) : Nil)
65− : (13 |> Nil)
58+ 1 :<
59+ (3 :< Nil)
60+ : (4 :< Nil)
61+ : (5 :<
62+ (10 :< Nil)
63+ : (11 :<
64+ (18 :< Nil) : Nil)
65+ : (13 :< Nil)
6666 : Nil
6767 )
6868 : Nil
69− shouldEqual (scanTree (\a b -> a + b) 0 sampleTree) result
69+ shouldEqual (eq (scanTree (\a b -> a + b) 0 sampleTree) result) true
7070
7171 describe "Zipper" do
7272
@@ -77,33 +77,33 @@ main = run [consoleReporter] do
7777 let root' = unsafePartial $ toTree $ modifyValue (\a -> 2 * a) (fromJust $ down root)
7878 let root'' = unsafePartial $ toTree $ modifyValue (\a -> 2 * a) (fromJust $ down >=> next >=> next >=> down $ root)
7979 let result =
80− 1 |>
81− (4 |> Nil)
82− : (3 |> Nil)
83− : (4 |>
84− (5 |> Nil)
85− : (6 |>
86− (7 |> Nil) : Nil)
87− : (8 |> Nil)
80+ 1 :<
81+ (4 :< Nil)
82+ : (3 :< Nil)
83+ : (4 :<
84+ (5 :< Nil)
85+ : (6 :<
86+ (7 :< Nil) : Nil)
87+ : (8 :< Nil)
8888 : Nil
8989 )
9090 : Nil
9191
9292 let result' =
93− 1 |>
94− (2 |> Nil)
95− : (3 |> Nil)
96− : (4 |>
97− (10 |> Nil)
98− : (6 |>
99− (7 |> Nil) : Nil)
100− : (8 |> Nil)
93+ 1 :<
94+ (2 :< Nil)
95+ : (3 :< Nil)
96+ : (4 :<
97+ (10 :< Nil)
98+ : (6 :<
99+ (7 :< Nil) : Nil)
100+ : (8 :< Nil)
101101 : Nil
102102 )
103103 : Nil
104104
105− shouldEqual root' result
106− shouldEqual root'' result'
105+ shouldEqual (eq root' result) true
106+ shouldEqual (eq root'' result') true
107107
108108 it "Insert" do
109109
@@ -111,32 +111,32 @@ main = run [consoleReporter] do
111111 let root'' = unsafePartial $ toTree $ insertAfter (mkTree 100 Nil) (fromJust $ (down root) >>= next >>= next >>= down >>= next >>= down)
112112
113113 let result =
114− 1 |>
115− (2 |> Nil)
116− : (100 |> Nil)
117− : (3 |> Nil)
118− : (4 |>
119− (5 |> Nil)
120− : (6 |>
121− (7 |> Nil) : Nil)
122− : (8 |> Nil)
114+ 1 :<
115+ (2 :< Nil)
116+ : (100 :< Nil)
117+ : (3 :< Nil)
118+ : (4 :<
119+ (5 :< Nil)
120+ : (6 :<
121+ (7 :< Nil) : Nil)
122+ : (8 :< Nil)
123123 : Nil
124124 )
125125 : Nil
126126
127127 let result' =
128− 1 |>
129− (2 |> Nil)
130− : (3 |> Nil)
131− : (4 |>
132− (5 |> Nil)
133− : (6 |>
134− (7 |> Nil)
135− : (100 |> Nil)
128+ 1 :<
129+ (2 :< Nil)
130+ : (3 :< Nil)
131+ : (4 :<
132+ (5 :< Nil)
133+ : (6 :<
134+ (7 :< Nil)
135+ : (100 :< Nil)
136136 : Nil)
137− : (8 |> Nil)
137+ : (8 :< Nil)
138138 : Nil
139139 )
140140 : Nil
141− shouldEqual root' result
142− shouldEqual root'' result'
141+ shouldEqual (eq root' result) true
142+ shouldEqual (eq root'' result') true