aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/data/sum.lux
blob: 224ba3878162ca1c7925a299be30d30a1edd4088 (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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
(.module:
  {#.doc "Functionality for working with variants (particularly 2-variants)."}
  [library
   [lux #*
    [abstract
     [equivalence (#+ Equivalence)]
     [hash (#+ Hash)]]]])

(template [<right?> <name> <doc>]
  [(def: #export (<name> value)
     {#.doc (doc <doc>)}
     (All [left right]
       (-> <name> (Or left right)))
     (0 <right?> value))]

  [#0 left
   "Lifts value to the left side of a 2-variant."]
  [#1 right
   "Lifts value to the right side of a 2-variant."])

(def: #export (either fl fr)
  {#.doc (doc "Applies a function to either side of a 2-variant.")}
  (All [a b c]
    (-> (-> a c) (-> b c)
        (-> (Or a b) c)))
  (function (_ input)
    (case input
      (0 #0 l) (fl l)
      (0 #1 r) (fr r))))

(def: #export (apply fl fr)
  {#.doc (doc "Applies functions to both sides of a 2-variant.")}
  (All [l l' r r']
    (-> (-> l l') (-> r r')
        (-> (Or l r) (Or l' r'))))
  (function (_ input)
    (case input
      (0 #0 l) (0 #0 (fl l))
      (0 #1 r) (0 #1 (fr r)))))

(template [<name> <side> <right?>]
  [(def: #export (<name> es)
     (All [a b] (-> (List (Or a b)) (List <side>)))
     (case es
       #.End
       #.End
       
       (#.Item (0 <right?> x) es')
       (#.Item [x (<name> es')])
       
       (#.Item _ es')
       (<name> es')))]

  [lefts  a #0]
  [rights b #1]
  )

(def: #export (partition xs)
  (All [a b] (-> (List (Or a b)) [(List a) (List b)]))
  (case xs
    #.End
    [#.End #.End]

    (#.Item x xs')
    (let [[lefts rights] (partition xs')]
      (case x
        (0 #0 x')  [(#.Item x' lefts) rights]
        (0 #1 x') [lefts (#.Item x' rights)]))))

(def: #export (equivalence left right)
  (All [l r] (-> (Equivalence l) (Equivalence r) (Equivalence (Or l r))))
  (implementation
   (def: (= reference sample)
     (case [reference sample]
       [(#.Left reference) (#.Left sample)]
       (\ left = reference sample)

       [(#.Right reference) (#.Right sample)]
       (\ right = reference sample)

       _
       false))))

(def: #export (hash left right)
  (All [l r] (-> (Hash l) (Hash r) (Hash (Or l r))))
  (implementation
   (def: &equivalence
     (..equivalence (\ left &equivalence)
                    (\ right &equivalence)))
   (def: (hash value)
     (case value
       (#.Left value)
       (\ left hash value)

       (#.Right value)
       (\ right hash value)))))