6 | import Derive.Prelude
8 | %language ElabReflection
17 | record Tree (a : Type) where
20 | forest : List (Tree a)
24 | Forest : Type -> Type
25 | Forest = List . Tree
27 | %runElab derive "Tree" [Show,Eq]
35 | singleton : a -> Tree a
36 | singleton a = T a []
41 | replicate : (width : Nat) -> (depth : Nat) -> a -> Tree a
42 | replicate _ 0 x = T x []
43 | replicate width (S k) x = T x $
replicate width (replicate width k x)
47 | unfold : (depth : Nat) -> (f : s -> (a,List s)) -> s -> Tree a
48 | unfold 0 f s = T (fst $
f s) []
51 | in T a (map (unfold k f) ss)
57 | zipWithKeep : (a -> a -> a) -> List a -> List a -> List a
58 | zipWithKeep f [] ys = ys
59 | zipWithKeep f xs [] = xs
60 | zipWithKeep f (x :: xs) (y :: ys) = f x y :: zipWithKeep f xs ys
64 | flatten : Tree a -> List a
65 | flatten (T v vs) = v :: flattenF vs
68 | flattenF : Forest a -> List a
70 | flattenF (x :: xs) = flatten x ++ flattenF xs
75 | layers : Tree a -> List (List a)
76 | layers (T v vs) = [v] :: layersF vs
79 | layersF : Forest a -> List (List a)
81 | layersF (x :: xs) = zipWithKeep (++) (layers x) (layersF xs)
89 | index : List Nat -> Tree a -> Maybe a
90 | index [] x = Just x.value
91 | index (y :: ys) x = ix y x.forest >>= index ys
94 | ix : Nat -> List b -> Maybe b
96 | ix 0 (z :: _) = Just z
97 | ix (S k) (_ :: zs) = ix k zs
104 | foldlTree : (a -> e -> a) -> a -> Tree e -> a
105 | foldlTree f acc (T v vs) = foldlF (f acc v) vs
108 | foldlF : a -> Forest e -> a
110 | foldlF y (x :: xs) = foldlF (foldlTree f y x) xs
112 | foldrTree : (e -> a -> a) -> a -> Tree e -> a
113 | foldrTree f acc (T v vs) = f v (foldrF acc vs)
116 | foldrF : a -> Forest e -> a
118 | foldrF y (x :: xs) = foldrTree f (foldrF y xs) x
120 | traverseTree : Applicative f => (a -> f b) -> Tree a -> f (Tree b)
121 | traverseTree fun (T v vs) = [| T (fun v) (traverseF vs) |]
124 | traverseF : Forest a -> f (Forest b)
125 | traverseF [] = pure []
126 | traverseF (x :: xs) = [| traverseTree fun x :: traverseF xs |]
128 | mapTree : (a -> b) -> Tree a -> Tree b
129 | mapTree f (T v vs) = T (f v) (mapF vs)
132 | mapF : Forest a -> Forest b
134 | mapF (h :: t) = mapTree f h :: mapF t
136 | bindTree : Tree a -> (a -> Tree b) -> Tree b
137 | bindTree (T va tas) f =
138 | let T vb tbs := f va
139 | in T vb (tbs ++ bindF tas)
142 | bindF : Forest a -> Forest b
144 | bindF (x :: xs) = bindTree x f :: bindF xs
146 | apTree : Tree (a -> b) -> Tree a -> Tree b
147 | apTree tf ta = bindTree tf $
\f => mapTree (apply f) ta
149 | joinTree : Tree (Tree a) -> Tree a
150 | joinTree (T (T va tas) ftas) =
151 | T va $
tas ++ joinF ftas
154 | joinF : Forest (Tree a) -> Forest a
156 | joinF (x :: xs) = joinTree x :: joinF xs
167 | drawTree : Tree String -> String
168 | drawTree = unlines . draw
171 | drawForest : Forest String -> String
172 | drawForest = unlines . map drawTree
174 | draw : Tree String -> List String
175 | draw (T x ts0) = lines x ++ subTrees ts0
178 | shift : String -> String -> List String -> List String
179 | shift first other tails =
180 | zipWith (++) (first :: replicate (length tails) other) tails
182 | subTrees : Forest String -> List String
184 | subTrees [t] = "│" :: shift "└╼" " " (draw t)
185 | subTrees (t::ts) = "│" :: shift "├╼" "│ " (draw t) ++ subTrees ts
187 | parameters (rev : Bool)
190 | lst = if rev then "┌─" else "└─"
192 | children : String -> List (Tree String) -> SnocList String -> SnocList String
193 | children _ [] ss = ss
194 | children pre [T l cs] ss =
195 | let s := pre ++ lst ++ "\{l}"
196 | in children (pre ++ " ") cs (ss :< s)
198 | children pre (T l cs :: xs) ss =
199 | let s := pre ++ "├─\{l}"
200 | ss2 := children (pre ++ "│ ") cs (ss :< s)
201 | in children pre xs ss2
210 | prettyTree : Tree String -> String
211 | prettyTree (T l cs) =
212 | let ss := children "" cs [<"\{l}"] <>> []
213 | in if rev then unlines (reverse ss) else unlines ss
219 | public export %inline
220 | Foldable Tree where
225 | public export %inline
229 | public export %inline
230 | Applicative Tree where
234 | public export %inline
239 | public export %inline
240 | Traversable Tree where
241 | traverse = traverseTree