\import Algebra.Group
\import Algebra.Monoid
\import Algebra.Pointed
\import Data.Array
\import Function.Meta ($)
\import Logic
\import Logic.Meta
\import Meta
\import Paths
\import Paths.Meta
\import Set
\import Set.Category
\import Set.Fin
\record FinSuppFunc \extends SetHom {
\override Cod : AddPointed
| fSupp : ∃ (s : Array Dom) ∀ i ((\Pi (j : Fin s.len) -> s j /= i) -> func i = 0)
}
\instance FinSuppFuncDec (M : DecSet) (R : AddPointed) {D : DecSet R} : DecSet (FinSuppFunc M R)
| decideEq f g => \case fSupp {f}, fSupp {g} \with {
| inP (s : Array, c), inP (s' : Array, c') =>
\case FinSet.search (\lam j => f (s j) /= g (s j)) (\lam j => decide), FinSet.search (\lam j => f (s' j) /= g (s' j)) (\lam j => decide) \with {
| yes (inP (j,d)), _ => no \lam p => d $ pmap {FinSuppFunc M R} (__ (s j)) p
| _, yes (inP (j,d)) => no \lam p => d $ pmap {FinSuppFunc M R} (__ (s' j)) p
| no q, no q' => yes $ exts \lam i => \case FinSet.search (\lam j => i = s j) (\lam j => decide), FinSet.search (\lam j => i = s' j) (\lam j => decide) \with {
| yes (inP (j,p)), _ => rewrite p $ tightness \lam e => q $ inP (j, Set#.apartNotEqual e)
| _, yes (inP (j,p)) => rewrite p $ tightness \lam e => q' $ inP (j, Set#.apartNotEqual e)
| no r, no r' => c i (\lam j p => r $ inP (j, inv p)) *> inv (c' i \lam j p => r' $ inP (j, inv p))
}
}
}
\instance FinSuppFuncAddPointed {A : BaseSet} {B : AddPointed} : AddPointed (FinSuppFunc A B)
| zro => \new FinSuppFunc {
| func _ => 0
| fSupp => inP (nil, \lam _ _ => idp)
}
\instance FinSuppFuncAddMonoid {A : BaseSet} {B : AddMonoid} : AddMonoid (FinSuppFunc A B)
| AddPointed => FinSuppFuncAddPointed
| + f g => \new FinSuppFunc {
| func a => f a + g a
| fSupp => \case fSupp {f}, fSupp {g} \with {
| inP (s,c), inP (s',c') => inP (s ++ s', \lam a d => pmap2 (+) (c a \lam j => rewrite ++.++_index-left in d (++.index-left j)) (c' a \lam j => rewrite ++.++_index-right in d (++.index-right j)) *> zro-left)
}
}
| zro-left => exts (\lam a => zro-left)
| zro-right => exts (\lam a => zro-right)
| +-assoc => exts (\lam a => +-assoc)
\instance FinSuppFuncAbMonoid {A : BaseSet} {B : AbMonoid} : AbMonoid (FinSuppFunc A B)
| AddMonoid => FinSuppFuncAddMonoid
| +-comm => exts (\lam a => +-comm)
\instance FinSuppFuncAddGroup {A : BaseSet} {B : AddGroup} : AddGroup (FinSuppFunc A B)
| AddMonoid => FinSuppFuncAddMonoid
| negative f => \new FinSuppFunc {
| func a => negative (f a)
| fSupp => TruncP.map (fSupp {f}) \lam c => (c.1, \lam a d => pmap negative (c.2 a d) *> B.negative_zro)
}
| negative-left => exts (\lam a => negative-left)
| negative-right => exts (\lam a => negative-right)
\instance FinSuppFuncAbGroup {A : BaseSet} {B : AbGroup} : AbGroup (FinSuppFunc A B)
| AddGroup => FinSuppFuncAddGroup
| +-comm => FinSuppFuncAbMonoid.+-comm