\import Algebra.Group
\import Algebra.Meta
\import Algebra.Monoid
\import Algebra.Pointed
\import Algebra.Ring
\import Arith.Nat
\import Data.Array
\import Data.Fin (fsuc/=, nat_fin_=)
\import Data.Or
\import Equiv
\import Function.Meta ($)
\import Logic
\import Logic.Meta
\import Meta
\import Order.Lattice
\import Order.LinearOrder
\import Paths
\import Paths.Meta
\import Set
\import Set.Fin
\class GradedCRing \extends CRing {
| isHomogen : E -> Nat -> \Prop
| homogen-zro {n : Nat} : isHomogen 0 n
| homogen-negative_ide : isHomogen -1 0
| homogen-+ {n : Nat} {a b : E} : isHomogen a n -> isHomogen b n -> isHomogen (a + b) n
| homogen-* {n m : Nat} {a b : E} : isHomogen a n -> isHomogen b m -> isHomogen (a * b) (n Nat.+ m)
| homogen-decomp (x : E) : ∃ (l : Array E) (\Pi (n : Fin l.len) -> isHomogen (l n) n) (BigSum l = x)
| homogen-unique (l : Array E) : (\Pi (n : Fin l.len) -> isHomogen (l n) n) -> BigSum l = 0 -> ∀ (x : l) (x = 0)
\func isHomogenArray (l : Array E) => \Pi (n : Fin l.len) -> isHomogen (l n) n
\lemma homogen-ide : isHomogen 1 0
=> transport (isHomogen __ 0) equation (homogen-* homogen-negative_ide homogen-negative_ide)
\lemma homogen-negative {n : Nat} {x : E} (xh : isHomogen x n) : isHomogen (negative x) n
=> transport (isHomogen __ n) equation (homogen-* homogen-negative_ide xh)
\lemma homogen-pow {a : E} {n m : Nat} (ah : isHomogen a n) : isHomogen (pow a m) (n Nat.* m) \elim m
| 0 => homogen-ide
| suc m => homogen-* (homogen-pow ah) ah
\lemma homogen-BigSum {l : Array E} {n : Nat} (p : ∀ (a : l) (isHomogen a n)) : isHomogen (BigSum l) n \elim l
| nil => homogen-zro
| a :: l => homogen-+ (p 0) (homogen-BigSum (\lam j => p (suc j)))
\lemma homogen-FinSum {J : FinSet} {a : J -> E} {n : Nat} (p : \Pi (j : J) -> isHomogen (a j) n) : isHomogen (FinSum a) n
=> \case FinSum_char a \with {
| inP (e,q) => transportInv (isHomogen __ n) q $ homogen-BigSum \lam j => p (e j)
}
\lemma homogen-similar {l l' : Array E} (lh : isHomogenArray l) (l'h : isHomogenArray l') (p : BigSum l = BigSum l') : Similar l l'
=> diff=0->similar $ homogen-unique (diff l l') (diff-homogen l l' 0 lh l'h) (diff-sum l l' *> toZero p)
\where {
\func diff (l l' : Array E) : Array E \elim l, l'
| nil, l' => map negative l'
| a :: l, nil => a :: l
| a :: l, a' :: l' => a - a' :: diff l l'
\lemma diff=0->similar {l l' : Array E} (p : \Pi (j : Fin (DArray.len {diff l l'})) -> diff l l' j = 0) : Similar l l' \elim l, l'
| nil, nil => nil-nil-similar
| nil, a :: l' => nil-::-similar (inv negative-isInv *> pmap negative (p 0) *> negative_zro) $ diff=0->similar \lam j => p (suc j)
| a :: nil, nil => ::-nil-similar (p 0) nil-nil-similar
| a :: a' :: l, nil => ::-nil-similar (p 0) $ diff=0->similar \lam j => p (suc j)
| a :: l, a' :: l' => ::-::-similar (fromZero $ p 0) $ diff=0->similar \lam j => p (suc j)
\lemma diff-sum (l l' : Array E) : BigSum (diff l l') = BigSum l - BigSum l' \elim l, l'
| nil, l' => inv $ zro-left *> BigSum_negative
| a :: l, nil => simplify
| a :: l, a' :: l' => equation {usingOnly (diff-sum l l')}
\lemma diff-homogen (l l' : Array E) (k : Nat)
(lh : \Pi (j : Fin l.len) -> isHomogen (l j) (k Nat.+ j))
(l'h : \Pi (j : Fin l'.len) -> isHomogen (l' j) (k Nat.+ j))
(j : Fin (DArray.len {diff l l'})) : isHomogen (diff l l' j) (k Nat.+ j) \elim l, l', j
| nil, a :: l', 0 => homogen-negative (l'h 0)
| nil, a :: l', suc j => homogen-negative (l'h (suc j))
| a :: l, nil, 0 => lh 0
| a :: a' :: l, nil, suc j => diff-homogen (a' :: l) nil (suc k) (\lam j => lh (suc j)) (\case __) j
| a :: l, a' :: l', 0 => homogen-+ (lh 0) (homogen-negative (l'h 0))
| a :: l, a' :: l', suc j => diff-homogen l l' (suc k) (\lam j => lh (suc j)) (\lam j => l'h (suc j)) j
}
\func degree-unique {a : E} {n m : Nat} (ahn : isHomogen a n) (ahm : isHomogen a m) : Or (a = 0) (n = m)
=> \case decideEq n m \with {
| yes e => inr e
| no q => inl $ rewrite (decideEq=_reduce $ inv $ fin-inc.char_nat {suc m} n) in
\let l => array2 n m a (negative a)
\in homogen-unique l (\lam j => mcases \with {
| yes p, d => rewriteI p ahn
| no n1, yes p => rewriteI p (homogen-negative ahm)
| no n1, no n2 => homogen-zro
}) (sum-lem2 {_} {l} (fin-inc {suc n} {suc m} n) (fin-inc-right {suc n} {suc m} m)
(\lam p => q $ inv (fin-inc.char_nat {suc m} n) *> p *> fin-inc-right.char_nat {suc n} m)
(\lam k p1 p2 => rewrite (decideEq/=_reduce \lam p => p1 $ fin_nat-inj $ inv $ fin-inc.char_nat {suc m} n *> p, decideEq/=_reduce \lam p => p2 $ fin_nat-inj $ inv $ fin-inc-right.char_nat {suc n} m *> p) idp)
*> rewrite (decideEq=_reduce $ inv $ fin-inc.char_nat {suc m} n, decideEq=_reduce $ inv $ fin-inc-right.char_nat {suc n} m, decideEq/=_reduce \lam p => q $ p *> fin-inc-right.char_nat {suc n} m) negative-right) (fin-inc {suc n} {suc m} n)
} \where {
\func array2 (n m : Nat) (a b : E) => \new Array E (suc n Nat.+ suc m) \lam j => \case decideEq n j, decideEq m j \with {
| yes _, _ => a
| no _, yes _ => b
| no _, no _ => 0
}
\lemma sum-lem1 {l : Array E} (i : Fin l.len) (c : \Pi (k : Fin l.len) -> k /= i -> l k = 0) : BigSum l = l i \elim l, i
| a :: l, 0 => pmap (a +) (BigSum_zro \lam j => c (suc j) (\case __)) *> zro-right
| a :: l, suc i => pmap (`+ _) (c 0 \case __) *> zro-left *> sum-lem1 i (\lam k d => c (suc k) (fsuc/= d))
\lemma sum-lem2 {l : Array E} (i j : Fin l.len) (i/=j : i /= j) (c : \Pi (k : Fin l.len) -> k /= i -> k /= j -> l k = 0) : BigSum l = l i + l j \elim l, i, j
| nil, i, _ => \case i
| a :: l, 0, 0 => \case i/=j idp
| a :: l, 0, suc j => pmap (a +) (sum-lem1 j \lam k d => c (suc k) (\case __) (fsuc/= d))
| a :: l, suc i, 0 => pmap (a +) (sum-lem1 i \lam k d => c (suc k) (fsuc/= d) (\case __)) *> +-comm
| a :: l, suc i, suc j => pmap (`+ _) (c 0 (\case __) (\case __)) *> zro-left *> sum-lem2 i j (\lam p => i/=j \lam i => suc (p i)) (\lam k d1 d2 => c (suc k) (fsuc/= d1) (fsuc/= d2))
}
\func degree-unique2 {a b c : E} {n m k : Nat} (p : a = b + c) (ah : isHomogen a n) (bh : isHomogen b m) (ch : isHomogen c k) : Or (Or (b = 0) (c = 0)) (m = k)
=> \case decideEq m k \with {
| yes m=k => inr m=k
| no m/=k => \let | l => degree-unique.array2 m k b c
| s => homogen-similar {_} {l} {replicate n zro ++ a :: nil} (\lam j => mcases \with {
| yes e, d => rewriteI e bh
| no _, yes e => rewriteI e ch
| no n1, no n2 => homogen-zro
}) (homogen-++ (\lam j => homogen-zro) $ later \lam (0) => ah) $
degree-unique.sum-lem2 {_} {l} (fin-inc {suc m} {suc k} m) (fin-inc-right {suc m} {suc k} k)
(\lam p => m/=k $ inv (fin-inc.char_nat {suc k} m) *> p *> fin-inc-right.char_nat {suc m} k)
(\lam l p1 p2 => rewrite (decideEq/=_reduce \lam p => p1 $ fin_nat-inj $ inv $ fin-inc.char_nat {suc k} m *> p, decideEq/=_reduce \lam p => p2 $ fin_nat-inj $ inv $ fin-inc-right.char_nat {suc m} k *> p) idp)
*> rewrite (decideEq=_reduce $ inv $ fin-inc.char_nat {suc k} m, decideEq=_reduce $ inv $ fin-inc-right.char_nat {suc m} k, decideEq/=_reduce \lam p => m/=k $ p *> fin-inc-right.char_nat {suc m} k) (inv p) *> inv (BigSum_++ *> pmap (`+ _) BigSum_replicate0 *> simplify)
\in \case decideEq n m \with {
| yes n=m => cases (decideEq m (fin-inc-right {suc m} k), decideEq k (fin-inc-right {suc m} k), similar-unique l a n s (fin-inc-right {suc m} {suc k} k) \lam p => m/=k $ inv n=m *> p *> fin-inc-right.char_nat {suc m} k) \with {
| yes e, _, t => inl (inl t)
| no n1, yes e, t => inl (inr t)
| no _, no c, t => absurd $ c $ inv $ fin-inc-right.char_nat {suc m} k
}
| no n/=m => inl $ inl $ rewrite (decideEq=_reduce $ inv $ fin-inc.char_nat {suc k} m) in similar-unique l a n s (fin-inc {suc m} {suc k} m) \lam p => n/=m $ p *> fin-inc.char_nat {suc k} m
}
}
\where {
\lemma similar-unique (l : Array E) (a : E) (n : Nat) (s : Similar l (replicate n zro ++ a :: nil)) (j : Fin l.len) (n/=j : n /= j) : l j = 0 \elim l, n, s, j
| a' :: l, 0, ::-::-similar p s, 0 => absurd (n/=j idp)
| a' :: l, 0, ::-::-similar p s, suc j => similar-nil s j
| a' :: l, suc n, ::-::-similar p s, 0 => p
| a' :: l, suc n, ::-::-similar p s, suc j => similar-unique l a n s j \lam q => n/=j (pmap suc q)
}
\func homogenSum-unique {l : Array E} (lh : isHomogenArray l) {n : Nat} (h : isHomogen (BigSum l) n)
: Or (\Sigma (j : Fin l.len) (BigSum l = l j) (j = {Nat} n)) (BigSum l = 0)
=> \case similar-eq (homogen-similar {_} {replicate n zro ++ BigSum l :: nil} (homogen-++ (\lam j => homogen-zro) $ later \lam (0) => h) lh $
BigSum_++ *> pmap2 (+) BigSum_replicate0 zro-right *> zro-left) (++.index-right 0) \with {
| inl r => inl (r.1, inv ++.++_index-right *> r.2, r.3 *> ++.index-right-nat)
| inr r => inr (inv ++.++_index-right *> r)
}
\lemma homogen-++ {l l' : Array E} (lh : isHomogenArray l) (l'h : \Pi (j : Fin l'.len) -> isHomogen (l' j) (l.len Nat.+ j)) : isHomogenArray (l ++ l')
=> aux 0 lh l'h
\where
\lemma aux {l l' : Array E} (n : Nat)
(lh : \Pi (j : Fin l.len) -> isHomogen (l j) (n Nat.+ j))
(l'h : \Pi (j : Fin l'.len) -> isHomogen (l' j) (n Nat.+ l.len Nat.+ j))
(j : Fin (DArray.len {l ++ l'}))
: isHomogen (++ l l' j) (n Nat.+ j) \elim l, j
| nil, j => l'h j
| a :: l, 0 => lh 0
| a :: l, suc j => aux (suc n) (\lam j => lh (suc j)) l'h j
\lemma homogen-factor {a b c : E} (b=ac : b = a * c) {n m : Nat} (bh : isHomogen b n) (ah : isHomogen a m)
: ∃ (c' : E) (k : Nat) (isHomogen c' k) (b = a * c')
=> TruncP.map (homogen-decomp c) \lam (l,lh,+l=c) => aux n m 0 lh $ homogen-similar
(homogen-++ (\lam j => homogen-zro) $ later \lam (0) => bh)
(homogen-++ (\lam j => homogen-zro) $ later \lam j => homogen-* ah (lh j))
(BigSum_++ *> pmap (`+ _) BigSum_replicate0 *> later (simplify $ b=ac *> pmap (a *) (inv +l=c) *> BigSum-ldistr) *> inv (BigSum_++ *> pmap (`+ _) BigSum_replicate))
\where {
\func aux {a b : E} (s t n : Nat) {l : Array E} (lh : \Pi (j : Fin l.len) -> isHomogen (l j) (n Nat.+ j)) (p : Similar (replicate s zro ++ b :: nil) (replicate t zro ++ map (a *) l))
: \Sigma (c : E) (k : Nat) (isHomogen c k) (b = a * c) \elim s, t, l, p
| 0, 0, nil, ::-nil-similar idp _ => (0, 0, homogen-zro, inv zro_*-right)
| 0, 0, c :: l, ::-::-similar p _ => (c, n, lh 0, p)
| 0, suc t, l, ::-::-similar idp _ => (0, 0, homogen-zro, inv zro_*-right)
| suc s, 0, nil, ::-nil-similar _ q => aux s 0 n lh q
| suc s, 0, c :: l, ::-::-similar _ q => aux s 0 (suc n) (\lam j => lh (suc j)) q
| suc s, suc t, l, ::-::-similar _ q => aux s t n lh q
}
\lemma homogen-factor2 {a1 a2 b c d : E} (b=ac : b = a1 * c + a2 * d) {n m1 m2 : Nat} (bh : isHomogen b n) (a1h : isHomogen a1 m1) (a2h : isHomogen a2 m2)
: ∃ (c' d' : E) (k1 k2 : Nat) (isHomogen c' k1) (isHomogen d' k2) (b = a1 * c' + a2 * d')
=> \case homogen-decomp c, homogen-decomp d \with {
| inP (l1,l1h,+l1=c1), inP (l2,l2h,+l2=c2) => inP $ aux n m1 m2 0 0 l1h l2h $ homogen-similar
(homogen-++ (\lam j => homogen-zro) $ later \lam (0) => bh)
(homogen-sum 0 (homogen-++ (\lam j => homogen-zro) (\lam j => later $ homogen-* a1h (l1h j))) (homogen-++ (\lam j => homogen-zro) (\lam j => later $ homogen-* a2h (l2h j))))
$ BigSum_++ *> pmap (`+ _) BigSum_replicate0 *> simplify b=ac *>
inv (BigSum_sum *> pmap2 (+) (BigSum_++ *> pmap (`+ _) BigSum_replicate0 *> zro-left) (BigSum_++ *> pmap (`+ _) BigSum_replicate0 *> zro-left) *> pmap2 (+) (inv BigSum-ldistr *> pmap (a1 *) +l1=c1) (inv BigSum-ldistr *> pmap (a2 *) +l2=c2))
}
\where {
\func sum (l l' : Array E) : Array E \elim l, l'
| nil, l' => l'
| a :: l, nil => a :: l
| a :: l, a' :: l' => a + a' :: sum l l'
\lemma sum_nil {l : Array E} : sum l nil = l \elim l
| nil => idp
| a :: l => idp
\lemma BigSum_sum {l l' : Array E} : BigSum (sum l l') = BigSum l + BigSum l' \elim l, l'
| nil, nil => inv zro-left
| nil, a :: l => inv zro-left
| a :: l, nil => inv zro-right
| a :: l, a' :: l' => pmap (_ +) BigSum_sum *> equation
\lemma homogen-sum {l l' : Array E} (n : Nat)
(lh : \Pi (j : Fin l.len) -> isHomogen (l j) (n Nat.+ j))
(l'h : \Pi (j : Fin l'.len) -> isHomogen (l' j) (n Nat.+ j))
(j : Fin (DArray.len {sum l l'}))
: isHomogen (sum l l' j) (n Nat.+ j) \elim l, l', j
| nil, a :: l, 0 => l'h 0
| nil, a :: l, suc j => l'h (suc j)
| a :: l, nil, 0 => lh 0
| a :: l, nil, suc j => lh (suc j)
| a :: l, a' :: l', 0 => homogen-+ (lh 0) (l'h 0)
| a :: l, a' :: l', suc j => homogen-sum (suc n) (\lam j => lh (suc j)) (\lam j => l'h (suc j)) j
\func aux {a1 a2 b : E} (s t1 t2 n1 n2 : Nat) {l1 l2 : Array E}
(l1h : \Pi (j : Fin l1.len) -> isHomogen (l1 j) (n1 Nat.+ j))
(l2h : \Pi (j : Fin l2.len) -> isHomogen (l2 j) (n2 Nat.+ j))
(p : Similar (replicate s zro ++ b :: nil) (sum (replicate t1 zro ++ map (a1 *) l1) (replicate t2 zro ++ map (a2 *) l2)))
: \Sigma (c1 c2 : E) (k1 k2 : Nat) (isHomogen c1 k1) (isHomogen c2 k2) (b = a1 * c1 + a2 * c2) \elim s, t1, t2, l1, l2, p
| 0, 0, 0, nil, nil, ::-nil-similar p _ => (0, 0, 0, 0, homogen-zro, homogen-zro, p *> simplify)
| 0, 0, 0, nil, c2 :: l2, ::-::-similar p q => (0, c2, 0, n2, homogen-zro, l2h 0, p *> simplify)
| 0, 0, 0, c1 :: l1, nil, ::-::-similar p q => (c1, 0, n1, 0, l1h 0, homogen-zro, p *> simplify)
| 0, 0, 0, c1 :: l1, c2 :: l2, ::-::-similar p _ => (c1, c2, n1, n2, l1h 0, l2h 0, p)
| 0, 0, suc t2, nil, _, ::-::-similar p _ => (0, 0, 0, 0, homogen-zro, homogen-zro, p *> simplify)
| 0, 0, suc t2, c1 :: l1, _, ::-::-similar p q => (c1, 0, n1, 0, l1h 0, homogen-zro, p *> simplify)
| 0, suc t1, 0, _, nil, ::-::-similar p q => (0, 0, 0, 0, homogen-zro, homogen-zro, p *> simplify)
| 0, suc t1, 0, _, c2 :: l2, ::-::-similar p q => (0, c2, 0, n2, homogen-zro, l2h 0, p *> simplify)
| 0, suc t1, suc t2, l1, l2, ::-::-similar p q => (0, 0, 0, 0, homogen-zro, homogen-zro, p *> simplify)
| suc s, 0, 0, nil, nil, ::-nil-similar _ q => aux s 0 0 n1 n2 l1h l2h q
| suc s, 0, 0, nil, c2 :: l2, ::-::-similar _ q => aux s 0 0 n1 (suc n2) l1h (\lam j => l2h (suc j)) q
| suc s, 0, 0, c1 :: l1, nil, ::-::-similar _ q => aux s 0 0 (suc n1) n2 (\lam j => l1h (suc j)) l2h (rewrite sum_nil q)
| suc s, 0, 0, c1 :: l1, c2 :: l2, ::-::-similar _ q => aux s 0 0 (suc n1) (suc n2) (\lam j => l1h (suc j)) (\lam j => l2h (suc j)) q
| suc s, 0, suc t2, nil, l2, ::-::-similar _ q => aux s 0 t2 n1 n2 l1h l2h q
| suc s, 0, suc t2, c1 :: l1, l2, ::-::-similar _ q => aux s 0 t2 (suc n1) n2 (\lam j => l1h (suc j)) l2h q
| suc s, suc t1, 0, l1, nil, ::-::-similar _ q => aux s t1 0 n1 n2 l1h l2h (rewrite sum_nil q)
| suc s, suc t1, 0, l1, c2 :: l2, ::-::-similar _ q => aux s t1 0 n1 (suc n2) l1h (\lam j => l2h (suc j)) q
| suc s, suc t1, suc t2, l1, l2, ::-::-similar _ q => aux s t1 t2 n1 n2 l1h l2h q
}
\lemma FinSum-homogen {J : FinSet} {a : J -> E} (p : \Pi (j : J) -> \Sigma (n : Nat) (isHomogen (a j) n)) : FinSum a = BigSum array
=> FinSum_Equiv (later \new QEquiv {
| f s => s.2.1
| ret j => ((p j).1, (j, inv $ mod_< $ FinJoin-cond _ <∘r id<suc))
| ret_f => unfold $ unfold $ unfold \lam s => exts (nat_fin_= $ mod_< (FinJoin-cond s.2.1 <∘r id<suc) *> s.2.2, idp)
| f_sec j => idp
}) *> inv (FinSum-double-dep (\lam i => SigmaFin J \lam j => DecFin (decideEq (p j).1 i)) {\lam s => a s.2.1}) *> FinSum=BigSum {_} {suc $ FinJoin (\lam j => (p j).1)}
\where {
\func array => \new Array E (suc $ FinJoin (\lam j => (p j).1)) \lam i => FinSum {_} {SigmaFin J \lam j => DecFin (decideEq (p j).1 i)} (\lam k => a k.1)
\lemma array-homogen : isHomogenArray array
=> \lam n => homogen-FinSum $ later \lam j => transport (isHomogen _) j.2 (p j.1).2
}
\lemma sum-decomp (l : Array (\Sigma E E)) (c : \Pi (i : Fin l.len) -> ∃ (n : Nat) (isHomogen (l i).2 n))
: ∃ (N : Nat) (f : \Pi (n : Fin N) -> \Sigma (J : FinSet) (g : J -> E) (\Pi (j : J) -> \Sigma (n : Nat) (isHomogen (g j) n)) (h : J -> Fin l.len) (\Pi (j : J) -> isHomogen (g j * (l (h j)).2) n))
(BigSum (map (\lam s => s.1 * s.2) l) = BigSum (\lam n => FinSum (\lam j => (f n).2 j * (l ((f n).4 j)).2)))
=> \let | (inP c') => FinSet.finiteAC c
| (inP d) => FinSet.finiteAC (\lam i => homogen-decomp (l i).1)
| p k : _ => later $ (k.2 Nat.+ (c' k.1).1, homogen-* ((d k.1).2 k.2) (c' k.1).2)
| q => path (\lam i => BigSum (\lam i' => inv (FinSum=BigSum *> (d i').3) i * (l i').2)) *> inv FinSum=BigSum *>
pmap FinSum (ext \lam j => FinSum-rdistr) *> FinSum-double-dep (\lam i => FinFin (DArray.len {(d i).1})) *> FinSum-homogen p
\in inP (suc _, \lam n => (SigmaFin (SigmaFin (FinFin l.len) (\lam i => FinFin (DArray.len {(d i).1}))) (\lam k => DecFin (decideEq (p k).1 n)), \lam k => (d k.1.1).1 k.1.2, \lam k => (k.1.2, (d k.1.1).2 k.1.2), __.1.1, \lam k => transport (isHomogen _) k.2 (p k.1).2), q)
} \where {
\open Bounded.JoinSemilattice
\data Similar {A : AddPointed} (l l' : Array A) \elim l, l'
| nil, nil => nil-nil-similar
| nil, a :: l' => nil-::-similar (a = 0) (Similar nil l')
| a :: l, nil => ::-nil-similar (a = 0) (Similar l nil)
| a :: l, a' :: l' => ::-::-similar (a = a') (Similar l l')
\lemma similar-nil {A : AddPointed} {l : Array A} (s : Similar l nil) (j : Fin l.len) : l j = 0 \elim l, s, j
| a :: l, ::-nil-similar p s, 0 => p
| a :: l, ::-nil-similar p s, suc j => similar-nil s j
\func similar-eq {A : AddPointed} {l l' : Array A} (s : Similar l l') (j : Fin l.len)
: Or (\Sigma (i : Fin l'.len) (l j = l' i) (i = {Nat} j)) (l j = 0) \elim l, l', s, j
| a :: l, nil, ::-nil-similar p s, 0 => inr p
| a :: l, nil, ::-nil-similar p s, suc j => \case similar-eq s j \with {
| inl r => \case r.1
| inr r => inr r
}
| a :: l, a' :: l', ::-::-similar p s, 0 => inl (0, p, idp)
| a :: l, a' :: l', ::-::-similar p s, suc j => \case similar-eq s j \with {
| inl r => inl (suc r.1, r.2, pmap suc r.3)
| inr r => inr r
}
}