2 | import public Data.Nat
3 | import public Data.DPair
4 | import Data.CheckedEmpty.List.Lazy
5 | import public Data.So
12 | data Nat1 : Type where
13 | FromNat : (n : Nat) -> (0 _ : IsSucc n) => Nat1
18 | toNat1 : Nat -> Maybe Nat1
20 | toNat1 k@(S _) = Just $
FromNat k
22 | public export %inline
23 | fromNat : (x : Nat) -> (0 _ : IsSucc x) => Nat1
26 | public export %inline
27 | toNat, (.asNat) : Nat1 -> Nat
28 | toNat $
FromNat n = n
35 | FromNat n == FromNat n' = n == n'
39 | compare = comparing $
\(FromNat n) => n
43 | public export %inline
44 | fromInteger : (x : Integer) -> (0 _ : So $
x >= 1) => Nat1
45 | fromInteger x = FromNat (cast x) @{believe_me $
ItIsSucc {n=1}}
49 | rangeFrom fr = rangeFrom fr.asNat <&> \x => FromNat x @{believe_me $
ItIsSucc {n=1}}
50 | rangeFromThen fr th = rangeFromThen fr.asNat th.asNat <&> \x => FromNat x @{believe_me $
ItIsSucc {n=1}}
51 | rangeFromTo fr to = rangeFromTo fr.asNat to.asNat <&> \x => FromNat x @{believe_me $
ItIsSucc {n=1}}
52 | rangeFromThenTo fr th to = rangeFromThenTo fr.asNat th.asNat to.asNat <&> \x => FromNat x @{believe_me $
ItIsSucc {n=1}}
56 | public export %inline
58 | succ $
FromNat n = FromNat (S n)
60 | public export %inline
64 | public export %inline
65 | (+) : Nat1 -> Nat1 -> Nat1
66 | FromNat (S n) + FromNat (S m) = FromNat (S n + S m)
68 | public export %inline
69 | (*) : Nat1 -> Nat1 -> Nat1
70 | FromNat (S n) * FromNat (S m) = FromNat (S n * S m)
77 | [Additive] Semigroup Nat1 where
81 | [Multiplicative] Semigroup Nat1 where
87 | [Multiplicative] Monoid Nat1 using Nat1.Semigroup.Multiplicative where
91 | [Maximum] Monoid Nat1 using Semigroup.Maximum where
97 | gcd : (a, b : Nat) -> (0 ok : Either (IsSucc a) (IsSucc b)) => Nat1
98 | gcd Z Z = void $
absurd ok
99 | gcd a@(S _) Z = FromNat a
100 | gcd Z b@(S _) = FromNat b
101 | gcd a (S b) = assert_total $
gcd (S b) (modNatNZ a (S b) %search)
104 | gcd' : Nat1 -> Nat1 -> Nat1
105 | gcd' (FromNat n) (FromNat m) = gcd n m
111 | pickWeighted : LazyLst1 (Nat1, a) -> Nat -> a
112 | pickWeighted [(_, x)] _ = x
113 | pickWeighted wh@((FromNat n, x)::y::ys) k = if k < n then x else pickWeighted (assert_smaller wh $
y::ys) (k `minus` n)
115 | foldmne : Foldable f => (a -> a -> a) -> f a -> Maybe a
116 | foldmne g = foldl gg Nothing where
117 | gg : Maybe a -> a -> Maybe a
118 | gg ml r = (ml <&> \l => g l r) <|> Just r
121 | normaliseWeights : Foldable f => Functor f => f (Nat1, a) -> f (Nat1, a)
122 | normaliseWeights xs = do
123 | let Just $
FromNat (S d) = foldmne gcd' $
Builtin.fst <$> xs
125 | flip map xs $
mapFst $
\(FromNat n) => FromNat (divNatNZ n (S d) %search) @{believe_me $
ItIsSucc {n=1} }