aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/data/number/ratio.lux
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/source/lux/data/number/ratio.lux')
-rw-r--r--stdlib/source/lux/data/number/ratio.lux119
1 files changed, 62 insertions, 57 deletions
diff --git a/stdlib/source/lux/data/number/ratio.lux b/stdlib/source/lux/data/number/ratio.lux
index 21176e998..9c7baaab8 100644
--- a/stdlib/source/lux/data/number/ratio.lux
+++ b/stdlib/source/lux/data/number/ratio.lux
@@ -3,6 +3,7 @@
[control
[equivalence (#+ Equivalence)]
[order (#+ Order)]
+ [monoid (#+ Monoid)]
number
codec
monad
@@ -12,9 +13,8 @@
["." product]
["." maybe]
[number
- ["." nat ("#;." decimal)]]
- ["." text ("#;." monoid)
- format]]
+ ["." nat ("#@." decimal)]]
+ ["." text ("#@." monoid)]]
["." function]
["." math]
["." macro
@@ -25,6 +25,13 @@
{#numerator Nat
#denominator Nat})
+(def: (equalize parameter subject)
+ (-> Ratio Ratio [Nat Nat])
+ [(n/* (get@ #denominator subject)
+ (get@ #numerator parameter))
+ (n/* (get@ #denominator parameter)
+ (get@ #numerator subject))])
+
(def: (normalize (^slots [#numerator #denominator]))
(-> Ratio Ratio)
(let [common (math.n/gcd numerator denominator)]
@@ -32,21 +39,19 @@
#denominator (n// common denominator)}))
(structure: #export equivalence (Equivalence Ratio)
- (def: (= param input)
- (and (n/= (get@ #numerator param)
- (get@ #numerator input))
- (n/= (get@ #denominator param)
- (get@ #denominator input)))))
+ (def: (= parameter subject)
+ (and (n/= (get@ #numerator parameter)
+ (get@ #numerator subject))
+ (n/= (get@ #denominator parameter)
+ (get@ #denominator subject)))))
(`` (structure: #export order (Order Ratio)
(def: &equivalence ..equivalence)
(~~ (do-template [<name> <op>]
- [(def: (<name> param input)
- (and (<op> (n/* (get@ #denominator input)
- (get@ #numerator param))
- (n/* (get@ #denominator param)
- (get@ #numerator input)))))]
+ [(def: (<name> parameter subject)
+ (let [[parameter' subject'] (..equalize parameter subject)]
+ (<op> parameter' subject')))]
[< n/<]
[<= n/<=]
@@ -66,46 +71,38 @@
[max >]
)
-(def: (- param input)
- (normalize [(n/- (n/* (get@ #denominator input)
- (get@ #numerator param))
- (n/* (get@ #denominator param)
- (get@ #numerator input)))
- (n/* (get@ #denominator param)
- (get@ #denominator input))]))
+(def: (- parameter subject)
+ (let [[parameter' subject'] (..equalize parameter subject)]
+ (normalize [(n/- parameter' subject')
+ (n/* (get@ #denominator parameter)
+ (get@ #denominator subject))])))
(structure: #export number
(Number Ratio)
- (def: (+ param input)
- (normalize [(n/+ (n/* (get@ #denominator input)
- (get@ #numerator param))
- (n/* (get@ #denominator param)
- (get@ #numerator input)))
- (n/* (get@ #denominator param)
- (get@ #denominator input))]))
+ (def: (+ parameter subject)
+ (let [[parameter' subject'] (..equalize parameter subject)]
+ (normalize [(n/+ parameter' subject')
+ (n/* (get@ #denominator parameter)
+ (get@ #denominator subject))])))
(def: - ..-)
- (def: (* param input)
- (normalize [(n/* (get@ #numerator param)
- (get@ #numerator input))
- (n/* (get@ #denominator param)
- (get@ #denominator input))]))
-
- (def: (/ param input)
- (normalize [(n/* (get@ #denominator param)
- (get@ #numerator input))
- (n/* (get@ #numerator param)
- (get@ #denominator input))]))
-
- (def: (% param input)
- (let [quot (n// (n/* (get@ #denominator input)
- (get@ #numerator param))
- (n/* (get@ #denominator param)
- (get@ #numerator input)))]
- (..- (update@ #numerator (n/* quot) param)
- input)))
+ (def: (* parameter subject)
+ (normalize [(n/* (get@ #numerator parameter)
+ (get@ #numerator subject))
+ (n/* (get@ #denominator parameter)
+ (get@ #denominator subject))]))
+
+ (def: (/ parameter subject)
+ (let [[parameter' subject'] (..equalize parameter subject)]
+ (normalize [subject' parameter'])))
+
+ (def: (% parameter subject)
+ (let [[parameter' subject'] (..equalize parameter subject)
+ quot (n// parameter' subject')]
+ (..- (update@ #numerator (n/* quot) parameter)
+ subject)))
(def: (negate (^slots [#numerator #denominator]))
{#numerator denominator
@@ -120,31 +117,39 @@
(def: separator Text ":")
-(def: part-encode
- (-> Nat Text)
- (|>> nat;encode (text.split 1) maybe.assume product.right))
-
(structure: #export codec (Codec Text Ratio)
(def: (encode (^slots [#numerator #denominator]))
- ($_ text;compose (part-encode numerator) separator (part-encode denominator)))
+ ($_ text@compose (nat@encode numerator) separator (nat@encode denominator)))
(def: (decode input)
(case (text.split-with separator input)
(#.Some [num denom])
(do error.monad
- [numerator (nat;decode num)
- denominator (nat;decode denom)]
+ [numerator (nat@decode num)
+ denominator (nat@decode denom)]
(wrap (normalize {#numerator numerator
#denominator denominator})))
#.None
- (#.Left (text;compose "Invalid syntax for ratio: " input)))))
+ (#.Left (text@compose "Invalid syntax for ratio: " input)))))
(syntax: #export (ratio numerator {?denominator (p.maybe s.any)})
{#.doc (doc "Rational literals."
(ratio numerator denominator)
"The denominator can be omitted if it's 1."
(ratio numerator))}
- (wrap (list (` ((~! normalize) {#..numerator (~ numerator)
- #..denominator (~ (maybe.default (' 1)
- ?denominator))})))))
+ (wrap (list (` ((~! ..normalize) {#..numerator (~ numerator)
+ #..denominator (~ (maybe.default (' 1)
+ ?denominator))})))))
+
+(do-template [<identity> <compose> <name>]
+ [(structure: #export <name>
+ (Monoid Ratio)
+
+ (def: identity (..ratio <identity>))
+ (def: compose (:: ..number <compose>))
+ )]
+
+ [0 + addition]
+ [1 * multiplication]
+ )