aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/world/money.lux
blob: 33764e8123ca08cae0bceb0628c737fa91f14ab6 (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
(.require
 [library
  [lux (.except)
   [abstract
    ["[0]" equivalence (.only Equivalence)]]
   [data
    ["[0]" product]
    ["[0]" text (.only)
     ["%" \\format]]]
   [math
    [number
     ["n" nat]]]
   [meta
    ["[0]" static]
    [type
     ["[0]" nominal]]]]]
 [/
  ["/" currency]])

(nominal.def .public (Money currency)
  (Record
   [#currency (/.Currency currency)
    #amount Nat])

  (def .public (money currency amount)
    (All (_ currency)
      (-> (/.Currency currency) Nat
          (Money currency)))
    (nominal.abstraction
     [#currency currency
      #amount amount]))

  (with_template [<name> <slot> <type>]
    [(def .public <name>
       (All (_ currency)
         (-> (Money currency)
             <type>))
       (|>> nominal.representation
            (the <slot>)))]

    [currency #currency (/.Currency currency)]
    [amount #amount Nat]
    )

  (def .public equivalence
    (All (_ of)
      (Equivalence (Money of)))
    (at equivalence.functor each
        (|>> nominal.representation)
        (all product.equivalence
             /.equivalence
             n.equivalence
             )))

  (def .public (+ parameter subject)
    (All (_ currency)
      (-> (Money currency) (Money currency)
          (Money currency)))
    (|> subject
        nominal.representation
        (revised #amount (n.+ (|> parameter nominal.representation (the #amount))))
        nominal.abstraction))

  (def .public (- parameter subject)
    (All (_ currency)
      (-> (Money currency) (Money currency)
          (Maybe (Money currency))))
    (let [parameter (nominal.representation parameter)
          subject (nominal.representation subject)]
      (if (n.< (the #amount parameter)
               (the #amount subject))
        {.#None}
        {.#Some (nominal.abstraction
                 [#currency (the #currency subject)
                  #amount (n.- (the #amount parameter)
                               (the #amount subject))])})))

  (def .public (format it)
    (All (_ currency)
      (%.Format (Money currency)))
    (let [[currency amount] (nominal.representation it)
          [macro micro] (n./% (/.subdivisions currency) amount)]
      (%.format (%.nat macro)
                (when micro
                  0 ""
                  _ (%.format "." (%.nat micro)))
                " " (/.alphabetic_code currency))))
  )