Skip to content

Commit 107c763

Browse files
feat(solutions): implement a BTree zipper
1 parent bfb9472 commit 107c763

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

Diff for: solutions/Utils/Tree.hs

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
module Utils.Tree (
2+
BTree (..),
3+
Context (..),
4+
Zipper,
5+
mkZipper,
6+
unZipper,
7+
up,
8+
down,
9+
topmost,
10+
insert,
11+
findChild,
12+
modify
13+
) where
14+
15+
import Data.Bifunctor (first)
16+
import Data.List (elemIndex, findIndex)
17+
18+
data BTree a = Node a [BTree a] | Leaf a
19+
deriving (Eq, Show, Functor)
20+
21+
data Context a = Root | Branch a [BTree a] [BTree a] (Context a)
22+
deriving (Eq, Show)
23+
24+
type Zipper a = (BTree a, Context a)
25+
26+
mkZipper :: BTree a -> Zipper a
27+
mkZipper t = (t, Root)
28+
29+
unZipper :: Zipper a -> BTree a
30+
unZipper = fst . topmost
31+
32+
up :: Zipper a -> Zipper a
33+
up z@(_, Root) = z
34+
up (tree, Branch x before after ctx) =
35+
(Node x (before ++ tree:after), ctx)
36+
37+
down :: Int -> Zipper a -> Zipper a
38+
down _ z@(Leaf _, _) = z
39+
down i (Node p children, ctx)
40+
| i < 0 || i >= length children = error "'i' out of range"
41+
| otherwise =
42+
let (before, x:after) = splitAt i children in
43+
(x, Branch p before after ctx)
44+
45+
topmost :: Zipper a -> Zipper a
46+
topmost z@(_, Root) = z
47+
topmost z = topmost $ up z
48+
49+
insert :: BTree a -> Zipper a -> Zipper a
50+
insert t = first (prependChild t)
51+
52+
prependChild :: BTree a -> BTree a -> BTree a
53+
prependChild _ (Leaf _) = error "cannot append a child node to a Leaf"
54+
prependChild child (Node x children) = Node x (child:children)
55+
56+
findChild :: (a -> Bool) -> Zipper a -> Maybe Int
57+
findChild _ (Leaf _, _) = Nothing
58+
findChild f (Node _ children, _) = findIndex f (value <$> children)
59+
60+
value :: BTree a -> a
61+
value (Leaf x) = x
62+
value (Node x _) = x
63+
64+
modify :: (a -> a) -> Zipper a -> Zipper a
65+
modify f (tree, ctx) = case tree of
66+
Node x children -> (Node (f x) children, ctx)
67+
Leaf x -> (Leaf (f x), ctx)

0 commit comments

Comments
 (0)