0 | module Data.Monoid.Exponentiation
2 | import Data.Nat.Views
3 | import Syntax.PreorderReasoning
11 | linear : Monoid a => a -> Nat -> a
12 | linear v Z = neutral
13 | linear v (S k) = v <+> linear v k
16 | modularRec : Monoid a => a -> HalfRec n -> a
17 | modularRec v HalfRecZ = neutral
18 | modularRec v (HalfRecEven _ acc) = let e = modularRec v acc in e <+> e
19 | modularRec v (HalfRecOdd _ acc) = let e = modularRec v acc in v <+> e <+> e
22 | modular : Monoid a => a -> Nat -> a
23 | modular v n = modularRec v (halfRec n)
27 | (^) : Num a => a -> Nat -> a
28 | (^) = modular @{Multiplicative}
35 | linearPlusHomo : (mon : Monoid a) =>
37 | (opAssoc : {0 x, y, z : a} -> ((x <+> y) <+> z) === (x <+> (y <+> z))) ->
38 | (neutralL : {0 x : a} -> (neutral @{mon} <+> x) === x) ->
40 | (v : a) -> {m, n : Nat} ->
41 | (linear v m <+> linear v n) === linear v (m + n)
42 | linearPlusHomo opAssoc neutralL v = go m where
44 | go : (m : Nat) -> (linear v m <+> linear v n) === linear v (m + n)
47 | |~ (v <+> linear v m) <+> linear v n
48 | ~~ v <+> (linear v m <+> linear v n) ...( opAssoc )
49 | ~~ v <+> (linear v (m + n)) ...( cong (v <+>) (go m) )
52 | modularRecCorrect : (mon : Monoid a) =>
54 | (opAssoc : {0 x, y, z : a} -> ((x <+> y) <+> z) === (x <+> (y <+> z))) ->
55 | (neutralL : {0 x : a} -> (neutral @{mon} <+> x) === x) ->
57 | (v : a) -> {n : Nat} -> (p : HalfRec n) ->
58 | modularRec v p === linear v n
59 | modularRecCorrect opAssoc neutralL v acc = go acc where
61 | aux : {m, n : Nat} -> (linear v m <+> linear v n) === linear v (m + n)
62 | aux = linearPlusHomo opAssoc neutralL v
64 | go : {n : Nat} -> (p : HalfRec n) -> modularRec v p === linear v n
66 | go (HalfRecEven k acc) = rewrite go acc in aux
67 | go (HalfRecOdd k acc) = rewrite go acc in Calc $
68 | |~ (v <+> linear v k) <+> linear v k
69 | ~~ v <+> (linear v k <+> linear v k) ...( opAssoc )
70 | ~~ v <+> (linear v (k + k)) ...( cong (v <+>) aux )
73 | modularCorrect : (mon : Monoid a) =>
75 | (opAssoc : {0 x, y, z : a} -> ((x <+> y) <+> z) === (x <+> (y <+> z))) ->
76 | (neutralL : {0 x : a} -> (neutral @{mon} <+> x) === x) ->
78 | (v : a) -> {n : Nat} -> modular v n === linear v n
79 | modularCorrect opAssoc neutralL v
80 | = modularRecCorrect opAssoc neutralL v (halfRec n)