aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/data/sum.lux
blob: 03e26b25d2c3d1822398bbe62a6f989bf23a69ee (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
(.require
 [library
  [lux (.except left right)
   [abstract
    [equivalence (.only Equivalence)]
    [hash (.only Hash)]]]])

(with_template [<right?> <name>]
  [(def .public (<name> value)
     (All (_ left right)
       (-> <name> (Or left right)))
     {0 <right?> value})]

  [#0 left]
  [#1 right])

(def .public (either on_left on_right)
  (All (_ a b c)
    (-> (-> a c) (-> b c)
        (-> (Or a b) c)))
  (function (_ input)
    (case input
      {0 #0 l} (on_left l)
      {0 #1 r} (on_right r))))

(def .public (then on_left on_right)
  (All (_ l l' r r')
    (-> (-> l l') (-> r r')
        (-> (Or l r) (Or l' r'))))
  (function (_ input)
    (case input
      {0 #0 l} {0 #0 (on_left l)}
      {0 #1 r} {0 #1 (on_right r)})))

(with_template [<name> <side> <right?>]
  [(def .public (<name> items)
     (All (_ a b) (-> (List (Or a b)) (List <side>)))
     (case items
       {.#End}
       {.#End}
       
       {.#Item {0 <right?> x} items'}
       {.#Item [x (<name> items')]}
       
       {.#Item _ items'}
       (<name> items')))]

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

(def .public (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 .public (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}]
       (at left = reference sample)

       [{.#Right reference} {.#Right sample}]
       (at right = reference sample)

       _
       false))))

(def .public (hash left right)
  (All (_ l r) (-> (Hash l) (Hash r) (Hash (Or l r))))
  (implementation
   (def equivalence
     (..equivalence (at left equivalence)
                    (at right equivalence)))
   (def (hash value)
     (.nat (case value
             {.#Left value}
             ("lux i64 *" +2 (.int (at left hash value)))

             {.#Right value}
             ("lux i64 *" +3 (.int (at right hash value))))))))