aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/data/collection/tree.lux
blob: eed5bd860307071e1866b136a5a30e8c6d82957b (plain)
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
(.module:
  [lux #*
   [abstract
    [functor (#+ Functor)]
    [monad (#+ Monad do)]
    [equivalence (#+ Equivalence)]
    [fold (#+ Fold)]]
   [control
    ["<>" parser
     ["<c>" code (#+ Parser)]]]
   [data
    [collection
     ["." list ("#@." monad fold)]]]
   ["." macro
    [syntax (#+ syntax:)]
    ["." code]]])

(type: #export (Tree a)
  {#value a
   #children (List (Tree a))})

(def: #export (flatten tree)
  (All [a] (-> (Tree a) (List a)))
  (#.Cons (get@ #value tree)
          (list@join (list@map flatten (get@ #children tree)))))

(def: #export (leaf value)
  (All [a] (-> a (Tree a)))
  {#value value
   #children (list)})

(def: #export (branch value children)
  (All [a] (-> a (List (Tree a)) (Tree a)))
  {#value value
   #children children})

(type: #rec Tree-Code
  [Code (List Tree-Code)])

(def: tree^
  (Parser Tree-Code)
  (|> (|>> <>.some <c>.record (<>.and <c>.any))
      <>.rec
      <>.some
      <c>.record
      (<>.and <c>.any)
      <c>.tuple))

(syntax: #export (tree {root tree^})
  {#.doc (doc "Tree literals."
              (tree Int [+10 {+20 {}
                              +30 {}
                              +40 {}}]))}
  (wrap (list (` (~ (loop [[value children] root]
                      (` {#value (~ value)
                          #children (list (~+ (list@map recur children)))})))))))

(structure: #export (equivalence Equivalence<a>)
  (All [a] (-> (Equivalence a) (Equivalence (Tree a))))
  
  (def: (= tx ty)
    (and (:: Equivalence<a> = (get@ #value tx) (get@ #value ty))
         (:: (list.equivalence (equivalence Equivalence<a>)) = (get@ #children tx) (get@ #children ty)))))

(structure: #export functor
  (Functor Tree)
  
  (def: (map f fa)
    {#value (f (get@ #value fa))
     #children (list@map (map f)
                         (get@ #children fa))}))

(structure: #export fold
  (Fold Tree)
  
  (def: (fold f init tree)
    (list@fold (function (_ tree' init') (fold f init' tree'))
               (f (get@ #value tree)
                  init)
               (get@ #children tree))))