Utils.List

module Utils.List where

This module contains definitions, functions and properties for different kinds lists, such as backwards lists, indexed lists, and lists indexed over indexed lists.

Imports

open import Data.Nat using (ℕ;zero;suc)
open import Data.List using (List;[];_∷_;_++_;map;foldr;length;head) public
open import Data.List.Properties using (foldr-++;++-cancelʳ;∷-injective)
open import Relation.Binary.PropositionalEquality using (_≡_;refl;sym;cong;trans;subst;subst-subst)
open import Data.Empty using (⊥;⊥-elim)
open import Data.Product using (Σ;_×_;_,_;proj₂)
open import Relation.Nullary using (¬_)

open import Utils using (≡-subst-removable)

Backward Lists

data Bwd (A : Set) : Set where
  [] : Bwd A
  _:<_ : Bwd A → A → Bwd A

infixl 5 _:<_

bwd-length : ∀{A} → Bwd A → ℕ
bwd-length [] = 0
bwd-length (az :< a) = suc (bwd-length az)

bwd-foldr : ∀{A B : Set} → (A → B → B) → B → Bwd A → B
bwd-foldr f e [] = e
bwd-foldr f e (bs :< x) = bwd-foldr f (f x e) bs

Fish and Chips

Fish (<><) and chips (<») are two operators to concatenate a backwards list and a list together, either by consing every snoc and obtaining a list, or by snoc-ing every cons and obtaining a backwards list.

_<>>_ : ∀{A} → Bwd A → List A → List A
[] <>> as = as
(az :< a) <>> as = az <>> (a ∷ as)

_<><_ : ∀{A} → Bwd A → List A → Bwd A
az <>< []       = az
az <>< (a ∷ as) = (az :< a) <>< as

Snoc for lists and cons for backwards lists.

_:<L_ : ∀{A : Set} → List A → A → List A
as :<L a = as ++ (a ∷ [])

_∷B_ : ∀{A : Set} → A → Bwd A → Bwd A
a ∷B []          = [] :< a
a ∷B (as' :< a') = (a ∷B as') :< a'

Useful lemmas

lemma<>1 : ∀{A}(xs : Bwd A)(ys : List A) → (xs <>< ys) <>> [] ≡ xs <>> ys
lemma<>1 xs []       = refl
lemma<>1 xs (x ∷ ys) = lemma<>1 (xs :< x) ys

lemma<>1' : ∀{A}(xs : Bwd A)(ys : List A) → xs ≡ [] <>< ys → xs <>> [] ≡ ys
lemma<>1' xs ys refl = lemma<>1 [] ys

lemma<>2 : ∀{A}(xs : Bwd A)(ys : List A) → ([] <>< (xs <>> ys)) ≡ xs <>< ys
lemma<>2 [] ys = refl
lemma<>2 (xs :< x) ys = lemma<>2 xs (x ∷ ys)

lemma<>2' : ∀{A}(xs : Bwd A)(ys : List A) → xs <>> [] ≡ ys → [] <>< ys ≡ xs
lemma<>2' xs ys refl = lemma<>2 xs []

lemma-<>>-++ : ∀{A : Set} bs (as as' : List A) →  bs <>> (as ++ as') ≡ (bs <>> as) ++ as'
lemma-<>>-++ [] as as' = refl
lemma-<>>-++ (bs :< x) as as' = lemma-<>>-++ bs (x ∷ as) as'

lemma-bwd-foldr : ∀{A B}(f : A → B → B)(e : B)(bs : Bwd A) → foldr f e (bs <>> []) ≡ bwd-foldr f e bs
lemma-bwd-foldr f e [] = refl
lemma-bwd-foldr f e (bs :< b) = trans (trans ((cong (foldr f e) (lemma-<>>-++ bs [] (b ∷ []))))
                                             (foldr-++ f e (bs <>> []) (b ∷ [])))
                                      (lemma-bwd-foldr f (f b e) bs)

Some cancellation lemmas

<><-cancelʳ : ∀{A : Set} (bs bs' : Bwd A) xs → bs <>< xs ≡ bs' <>< xs → bs ≡ bs'
<><-cancelʳ bs bs' [] p = p
<><-cancelʳ bs bs' (x ∷ xs) p with <><-cancelʳ (bs :< x) (bs' :< x) xs p
... | refl = refl

<>>[]-cancelʳ : ∀{A : Set} (bs bs' : Bwd A) → bs <>> [] ≡ bs' <>> [] → bs ≡ bs'
<>>[]-cancelʳ bs bs' p = trans (sym (lemma<>2' bs (bs' <>> []) p)) (lemma<>2 bs' [])

<>>-cancelʳ : ∀{A : Set} (bs bs' : Bwd A) xs → bs <>> xs ≡ bs' <>> xs → bs ≡ bs'
<>>-cancelʳ bs bs' xs p = <>>[]-cancelʳ bs bs'
        (++-cancelʳ xs (bs <>> []) (bs' <>> [])
          (trans
            (sym (lemma-<>>-++ bs [] xs))
            (trans p (lemma-<>>-++ bs' [] xs))
          )
        )

<>>-cancelˡ : ∀{A : Set} (bs : Bwd A) xs xs' → bs <>> xs ≡ bs <>> xs' → xs ≡ xs'
<>>-cancelˡ [] xs xs' p = p
<>>-cancelˡ (bs :< x) xs xs' p with <>>-cancelˡ bs (x ∷ xs) (x ∷ xs') p
... | refl = refl

Indexed Lists

Indexed lists IList are lists of elements of an indexed set. They are indexed by the list of all indices which index its elements.

data IList {A : Set}(B : A → Set) : List A → Set where
  [] : IList B []
  _∷_ : ∀{ty ts} → B ty → IList B ts →  IList B (ty ∷ ts)

-- Concatenation for Indexed Lists
_++I_ : ∀{A : Set}{B : A → Set}{ts ts' : List A}
      → IList B ts → IList B ts' → IList B (ts ++ ts')
[] ++I bs = bs
(x ∷ as) ++I bs = x ∷ (as ++I bs)

lengthT : ∀{A : Set}{ts : List A}{B : A → Set} → IList B ts → ℕ
lengthT {ts = ts} _ = length ts

iGetIdx : ∀{A : Set}{ts : List A}{B : A → Set} → IList B ts → List A
iGetIdx {ts = ts} ils = ts

-- snoc for Indexed Lists.
_:<I_ : ∀{A : Set}{B : A → Set}{t}{ts : List A} → IList B ts → B t → IList B (ts :<L t)
as :<I a = as ++I (a ∷ [])

-- Injectivity of cons
∷-injectiveI : ∀ {A : Set}{B : A → Set}{t : A}{ts ts' : List A}
    {X Y : B t}{Xs : IList B ts}{Ys : IList B ts'}
    → (p : t ∷ ts' ≡ t ∷ ts)
    → _≡_ {_} {IList B (t ∷ ts)} (X ∷ Xs)  (subst (IList B) p (Y ∷ Ys))
    → X ≡ Y × Xs ≡ subst (IList B) (proj₂ (∷-injective p)) Ys
∷-injectiveI refl refl = refl , refl

Backwards Indexed Lists

data IBwd {A : Set}(B : A → Set) : Bwd A → Set where
  [] : IBwd B []
  _:<_ : ∀{ty ts}  → IBwd B ts → B ty → IBwd B (ts :< ty)

-- Chip for indexed lists
_<>>I_ :  ∀{A : Set}{B : A → Set}{bs : Bwd A}{ts : List A}
      → IBwd B bs → IList B ts → IList B (bs <>> ts)
[] <>>I tls = tls
(tbs :< x) <>>I tls = tbs <>>I (x ∷ tls)

_<><I_ :  ∀{A : Set}{B : A → Set}{bs : Bwd A}{ts : List A}
      → IBwd B bs → IList B ts → IBwd B (bs <>< ts)
ibs <><I [] = ibs
ibs <><I (x ∷ its) = (ibs :< x) <><I its

lemma<>I1 : ∀{A}{B : A → Set}{xs : Bwd A}{ys : List A} → (ixs : IBwd B xs) → (iys : IList B ys)
                  → (subst (IList B) (lemma<>1 xs ys) ((ixs <><I iys) <>>I [])) ≡ ixs <>>I iys
lemma<>I1 ixs [] = refl
lemma<>I1 ixs (iy ∷ iys) = lemma<>I1 (ixs :< iy) iys

lemma<>I2 : ∀{A}{B : A → Set}{xs : Bwd A}{ys : List A}(ixs : IBwd B xs)(iys : IList B ys)
                  → subst (IBwd B) (lemma<>2 xs ys) ([] <><I (ixs <>>I iys)) ≡ ixs <><I iys
lemma<>I2 [] iys = refl
lemma<>I2 (ixs :< ix) iys = lemma<>I2 ixs (ix ∷ iys)

lemma<>I2' : ∀{A}{B : A → Set}{xs : Bwd A}{ys : List A}(ixs : IBwd B xs)(iys : IList B ys)
                  → ([] <><I (ixs <>>I iys)) ≡ subst (IBwd B) (sym (lemma<>2 xs ys)) (ixs <><I iys)
lemma<>I2' [] iys = refl
lemma<>I2' (ixs :< ix) iys = lemma<>I2' ixs (ix ∷ iys)

IBwd2IList' : ∀{A}{B : A → Set}{bs}{ts} → (bs ≡ [] <>< ts) → IBwd B bs → IList B ts
IBwd2IList' {ts = ts} p tbs = subst (IList _) (trans (cong (_<>> []) p) (lemma<>1 [] ts)) (tbs <>>I [])

IBwd2IList : ∀{A}{B : A → Set}{bs}{ts} → (bs <>> [] ≡ ts) → IBwd B bs → IList B ts
IBwd2IList p tbs = subst (IList _) p (tbs <>>I [])

IList2IBwd : ∀{A}{B : A → Set}{ts}{bs} → ([] <>< ts ≡ bs) → IList B ts → IBwd B bs
IList2IBwd {ts = ts} p tbs = subst (IBwd _) p ([] <><I tbs)

IBwd<>IList : ∀{A}{B : A → Set}{bs}{ts} → (p : bs <>> [] ≡ ts) → {ibs : IBwd B bs}
            → {its : IList B ts}
            → IBwd2IList p ibs ≡ its
            → ibs ≡ IList2IBwd (lemma<>2' _ _ p) its
IBwd<>IList refl {ibs} refl rewrite lemma<>I2 ibs [] = refl

split :  ∀{A : Set} bs (ts : List A){B : A → Set} → IList B (bs <>> ts) → IBwd B bs × IList B ts
split [] ts vs = [] , vs
split (bs :< x) ts vs with split bs (x ∷ ts) vs
... | ls , (x ∷ rs) = ls :< x , rs

bsplit : ∀{A : Set} bs (ts : List A){B : A → Set} → IBwd B (bs <>< ts) → IBwd B bs × IList B ts
bsplit bs [] vs = vs , []
bsplit bs (x ∷ ts) vs with bsplit (bs :< x) ts vs
... | ls :< x , rs = ls , (x ∷ rs)

inj-IBwd2IList : ∀{A}{B : A → Set}{Bs}{As : List A}{ts ts' : IBwd B Bs}
           → (p : Bs <>> [] ≡ As)
           → IBwd2IList {ts = As} p ts ≡ IBwd2IList p ts'
           → ts ≡ ts'
inj-IBwd2IList refl q = trans (trans (sym (lemma<>I2 _ [])) (cong (IList2IBwd (lemma<>2' _ _ refl)) q)) (lemma<>I2 _ [])

A type for Zipper indexes

The following datatype allow us to index zippers of indexed lists.

data _≣_<>>_ {A : Set} : (as : List A) → Bwd A → List A → Set where
  start : ∀{as} → as ≣ [] <>> as
  bubble : ∀{as}{vs : Bwd A}{t}{ts : List A}
         → as ≣ vs <>> (t ∷ ts)
           ---------------------------
         → as ≣ (vs :< t) <>> ts

lem-≣-<>> : ∀{A : Set}{tot vs}{ts : List A} → tot ≣ vs <>> ts → tot ≡ vs <>> ts
lem-≣-<>> start = refl
lem-≣-<>> (bubble x) = lem-≣-<>> x

lem-≣-<>>' : ∀{A : Set}{tot vs}{ts : List A} → tot ≡ vs <>> ts → tot ≣ vs <>> ts
lem-≣-<>>' {vs = []} refl = start
lem-≣-<>>' {vs = vs :< x}{ts} refl = bubble (lem-≣-<>>' refl)

done-≣-<>> : ∀{A : Set}{tot : List A} → tot ≣ ([] <>< tot) <>> []
done-≣-<>> = lem-≣-<>>' (sym (lemma<>1 [] _))

no-empty-≣-<>> : ∀{A : Set}{vs}{h : A}{ts} → [] ≣ vs <>> (h ∷ ts) → ⊥
no-empty-≣-<>> (bubble r) = no-empty-≣-<>> r

unique-≣-<>> : ∀{A : Set}{tot vs}{ts : List A}(p q : tot ≣ vs <>> ts) → p ≡ q
unique-≣-<>> start start = refl
unique-≣-<>> (bubble p) (bubble q) with unique-≣-<>> p q
... | refl = refl

lemma-≣-<>>-refl : ∀{A}(xs : Bwd A)(ys : List A) → (xs <>> ys) ≣ xs <>> ys
lemma-≣-<>>-refl [] ys = start
lemma-≣-<>>-refl (xs :< x) ys = bubble (lemma-≣-<>>-refl xs (x ∷ ys))

Lists indexed by an indexed list

data IIList {A : Set}{B : A → Set}(C : ∀{a : A}(b : B a) → Set) : ∀{is} → IList B is → Set where
  [] : IIList C []
  _∷_ : ∀{a as}{i : B a}{is : IList B as} → C i → IIList C is → IIList C (i ∷ is)


data IIBwd {A : Set}{B : A → Set}(C : ∀{a : A}→ B a → Set) : ∀{is} → IBwd B is → Set where
  [] : IIBwd C []
  _:<_ : ∀{a as}{i : B a}{is : IBwd B as} → IIBwd C is → C i → IIBwd C (is :< i)

-- Chip for double indexed lists
_<>>II_ :  ∀{A : Set}{B : A → Set}{C : ∀{a : A}(b : B a) → Set}{bs : Bwd A}{ts : List A}
        {ibs : IBwd B bs}{its : IList B ts}
      → IIBwd C ibs → IIList C its → IIList C (ibs <>>I its)
[] <>>II tls = tls
(tbs :< x) <>>II tls = tbs <>>II (x ∷ tls)

-- Convert an IIBwd into an IIList
IIBwd2IIList : ∀{A}{B : A → Set}{C : ∀{a : A}(b : B a) → Set}{bs}{ts : List A}
               {ibs : IBwd B bs}{its : IList B ts}
             → (p : bs <>> [] ≡ ts)
             → (q : subst (IList B) p (ibs <>>I []) ≡  its)
             → IIBwd C ibs
             → IIList C its
IIBwd2IIList refl refl tbs = tbs <>>II []

-- Split an IIList
splitI : ∀{A : Set}{bs}{ts : List A}{B : A → Set}{C : ∀{a : A}(b : B a) → Set}
           (ibs : IBwd B bs)(its : IList B ts)
        → IIList C (ibs <>>I its) → IIBwd C ibs × IIList C its
splitI [] its xs = [] , xs
splitI (ibs :< x) its xs with splitI ibs (x ∷ its) xs
... | ls , (y ∷ rs) = (ls :< y) , rs

-- Split an IIBwd
bsplitI : ∀{A : Set}{bs}{ts : List A}{B : A → Set}{C : ∀{a : A}(b : B a) → Set}
           (ibs : IBwd B bs)(its : IList B ts)
        → IIBwd C (ibs <><I its) → IIBwd C ibs × IIList C its
bsplitI ibs [] vs = vs , []
bsplitI ibs (x ∷ its) vs with bsplitI (ibs :< x) its vs
... | ls :< x , rs = ls , (x ∷ rs)

-- project from an IIList
proj-IIList : ∀{A : Set}{B : A → Set}{C : ∀{a : A}(b : B a) → Set}
              {a} (b : B a) {Bs}{Fs}
              (bs : IBwd B Bs) (fs : IList B Fs)
             → IIList C (bs <>>I (b ∷ fs))
             → C b
proj-IIList b bs fs xs with splitI bs (b ∷ fs) xs
... | _ , (Cb ∷ _) = Cb

-- project from an IIBwd
proj-IIBwd : ∀{A : Set}{B : A → Set}{C : ∀{a : A}(b : B a) → Set}
              {a} (b : B a) {Bs}{Fs}
              (bs : IBwd B Bs) (fs : IList B Fs)
             → IIBwd C (bs <><I (b ∷ fs))
             → C b
proj-IIBwd b bs fs xs with bsplitI bs (b ∷ fs) xs
... | _ , (Cb ∷ _) = Cb

Index for IIList zippers

data _≣I_<>>_ {A : Set}{B : A → Set}{tot}(itot : IList B tot) :
                                        ∀{bs ts}
                                      → IBwd B bs
                                      → IList B ts
                                      → (tot ≣ bs <>> ts)
                                      → Set where
  start : (itot ≣I [] <>> itot) start
  bubble : ∀{bs}{ibs : IBwd B bs}{t}{it : B t}{ts}{ils : IList B ts}{idx}
         → (itot ≣I ibs <>> (it ∷ ils)) idx
           ------------------------------------------
         → (itot ≣I (ibs :< it) <>> ils) (bubble idx)

lem-≣I-<>>1 : ∀{A : Set}{B : A → Set}{tot : List A}{itot : IList B tot}{bs}
                                {ibs : IBwd B bs}{ls}{ils : IList B ls}
                                {idx : tot ≣ bs <>> ls}
                           → (itot ≣I ibs <>> ils) idx
                           → subst (IList B) (lem-≣-<>> idx) itot ≡ (ibs <>>I ils)
lem-≣I-<>>1 start = refl
lem-≣I-<>>1 (bubble x) = lem-≣I-<>>1 x

lem-≣I-<>>1' : ∀{A : Set}{B : A → Set}{tot : List A}{itot : IList B tot}{bs}
                                {ibs : IBwd B bs}{ls}{ils : IList B ls}
                                {idx : tot ≣ bs <>> ls}
                           → (itot ≣I ibs <>> ils) idx
                           → itot ≡ subst (IList B)  (sym (lem-≣-<>> idx)) (ibs <>>I ils)
lem-≣I-<>>1' start = refl
lem-≣I-<>>1' (bubble r) = lem-≣I-<>>1' r

lem-≣I-<>>2 : ∀{A : Set}{B : A → Set}{tot : List A}{itot : IList B tot}{bs}
                             {ibs : IBwd B bs}{ls}{ils : IList B ls}
                             (eq : bs <>> ls ≡ tot)
                           → itot ≡ subst (IList B) eq ((ibs <>>I ils))
                           → (itot ≣I ibs <>> ils) (lem-≣-<>>' (sym eq))
lem-≣I-<>>2 {ibs = []} refl refl = start
lem-≣I-<>>2 {ibs = ibs :< x} refl refl = bubble (lem-≣I-<>>2 refl refl)

lem-≣I-<>>2' : ∀{A : Set}{B : A → Set}{tot : List A}{itot : IList B tot}{bs}
                             {ibs : IBwd B bs}{ls}{ils : IList B ls}
                             (eq : tot ≡ bs <>> ls)
                           → (subst (IList B) eq itot) ≡ ((ibs <>>I ils))
                           → (itot ≣I ibs <>> ils) (lem-≣-<>>' eq)
lem-≣I-<>>2' {ibs = []} refl refl = start
lem-≣I-<>>2' {ibs = ibs :< x} refl refl = bubble (lem-≣I-<>>2' refl refl)

done-≣I-<>> : ∀{A : Set}{B : A → Set}{tot : List A}(itot : IList B tot) → (itot ≣I ([] <><I itot) <>> []) done-≣-<>>
done-≣I-<>> itot = lem-≣I-<>>2 (lemma<>1 [] _) (sym (lemma<>I1 [] itot))

lemma<>I3 : ∀{A}{B : A → Set}{bs : Bwd A}
          → (ibs : IBwd B bs)(iys : IList B (bs <>> []))
          → ibs <>>I [] ≡ iys → subst (IBwd B) (lemma<>2 bs []) ([] <><I iys) ≡ ibs
lemma<>I3 xs ys refl = lemma<>I2 xs []

lem-<><I-subst :  ∀{A : Set}{B : A → Set}{tot tot' : List A}{itot : IList B tot}
      → (p : tot ≡ tot')
      → ([] <><I subst (IList B) p itot) ≡ subst (IBwd B) (cong ([] <><_) p) ([] <><I itot)
lem-<><I-subst refl = refl

lemma-<>>I-++I : ∀{A : Set}{B : A → Set}{bs}{as as' : List A}
        → (ibs : IBwd B bs)(ias : IList B as)(ias' : IList B as')
        →  ibs <>>I (ias ++I ias') ≡  subst (IList B) (sym (lemma-<>>-++ bs as as')) ((ibs <>>I ias) ++I ias')
lemma-<>>I-++I [] ias ias' = refl
lemma-<>>I-++I (ibs :< x) ias ias' = lemma-<>>I-++I ibs (x ∷ ias) ias'

Cancellation law for <»I

<>>I[]-cancelʳ : ∀{A : Set}{B : A → Set}{bs : Bwd A}(ibs ibs' : IBwd B bs)
               → ibs <>>I [] ≡ ibs' <>>I [] → ibs ≡ ibs'
<>>I[]-cancelʳ ibs ibs' p = trans (sym (lemma<>I3 ibs (ibs' <>>I []) p)) (lemma<>I2 ibs' [])

<>>I-cancelˡ : ∀{A : Set}{B : A → Set}{bs : Bwd A}{xs}
                (ibs : IBwd B bs)
              → (ixs ixs' : IList B xs)
              → ibs <>>I ixs ≡ ibs <>>I ixs' → ixs ≡ ixs'
<>>I-cancelˡ [] ixs ixs' p = p
<>>I-cancelˡ (ibs :< x) ixs ixs' p with <>>I-cancelˡ ibs (x ∷ ixs) (x ∷ ixs') p
... | refl = refl

We may have that Bs <»I (H :: Fs) ≡ Bs’ <»I (H’ :: Fs’). We cannot conclude that Bs ≡ Bs’, H ≡ H’ and Fs ≡ Fs’, because the focus could be at different places of the same indexed list. However, if there is a predicate P such that P holds for every element of Bs and Bs’, but ¬(P H) and ¬(P H’), then this determines where the focus is and we may conclude that Bs ≡ Bs’, H ≡ H’ and Fs ≡ Fs’.

equalbyPredicate++ : ∀{A : Set}
                    (P : A → Set)
                    {bs bs' : List A}{fs fs'}
                    {tot : List A}
                    {h h' : A}
                  → (p : tot ≡ bs ++ (h ∷ fs))
                  → (p' : tot ≡ bs' ++ (h' ∷ fs'))
                  → (IList P bs)
                  → (IList P bs')
                  → (¬Ph : ¬(P h))
                  → (¬Ph' : ¬(P h'))
                  → bs ≡ bs'
equalbyPredicate++ P p p' [] [] ¬Ph ¬Ph' = refl
equalbyPredicate++ P refl refl [] (x ∷ ps') ¬Ph ¬Ph' = ⊥-elim (¬Ph x)
equalbyPredicate++ P refl refl (x ∷ ps) [] ¬Ph ¬Ph' = ⊥-elim (¬Ph' x)
equalbyPredicate++ P {a ∷ as} refl p' (x ∷ ps) (x₁ ∷ ps') ¬Ph ¬Ph' with ∷-injective p'
... | refl , q = cong (a ∷_) (equalbyPredicate++ P {as} refl q ps ps' ¬Ph ¬Ph')


equalbyPredicate : ∀{A : Set}
                    (P : A → Set)
                    {bs bs' : Bwd A}{fs fs'}{tot}
                    {h h' : A}
                  → (p : tot ≡ bs <>> (h ∷ fs))
                  → (p' : tot ≡ bs' <>> (h' ∷ fs'))
                  → (IBwd P bs)
                  → (IBwd P bs')
                  → (¬Ph : ¬(P h))
                  → (¬Ph' : ¬(P h'))
                  → bs ≡ bs'
equalbyPredicate P {bs} {bs'} {fs} {fs'} {tot} {h} {h'} p p' ps ps' ¬Ph ¬Ph' =
    <>>[]-cancelʳ _ _ (equalbyPredicate++ P
                      (trans p (lemma-<>>-++ bs [] (h ∷ fs)))
                      (trans p' (lemma-<>>-++ bs' [] (h' ∷ fs')))
                      (IBwd2IList refl ps)
                      (IBwd2IList refl ps')
                      ¬Ph
                      ¬Ph')

equalbyPredicate++I : ∀{A : Set}{B : A → Set}{bs bs' : List A}{fs fs'}{tot}
                    (TOT : IList B tot)
                    {Bs : IList B bs}{Bs' : IList B bs'}
                    {Fs : IList B fs}{Fs' : IList B fs'}
                    {h h' : A}
                    {H : B h}{H' : B h'}
                  → (P : {a : A} → B a → Set)
                  → (p : tot ≡ bs ++ (h ∷ fs))
                  → (p' : tot ≡ bs' ++ (h' ∷ fs'))
                  → (q : TOT ≡ subst (IList B) (sym p) (Bs ++I (H ∷ Fs)))
                  → (q' : TOT ≡ subst (IList B) (sym p') (Bs' ++I (H' ∷ Fs')))
                  → (ps : IIList P Bs)
                  → (ps' : IIList P Bs')
                  → (¬PH : ¬(P H))
                  → (¬PH' : ¬(P H'))
                  → Σ (bs ≡ bs') (λ { refl →
                    Σ (h ≡ h')   (λ { refl →
                    Σ (fs ≡ fs') (λ { refl → Bs ≡ Bs' }) }) })
equalbyPredicate++I TOT P p p' q q' [] [] ¬PH ¬PH' with ∷-injective (trans (sym p) p')
... | refl , refl = refl , (refl , (refl , refl))
equalbyPredicate++I TOT P refl refl refl refl [] (x ∷ ps') ¬PH ¬PH' = ⊥-elim (¬PH x)
equalbyPredicate++I TOT P refl refl refl refl (x ∷ ps) [] ¬PH ¬PH' = ⊥-elim (¬PH' x)
equalbyPredicate++I TOT P refl p' refl q' (x ∷ ps) (x₁ ∷ ps') ¬PH ¬PH' with ∷-injective p'
... | refl , pt with ∷-injectiveI (sym p') q'
... | refl , qt with equalbyPredicate++I _ P refl pt refl
                                       (trans qt (≡-subst-removable (IList _) (proj₂ (∷-injective (sym p'))) (sym pt) _))
                                        ps ps' ¬PH ¬PH'
... | refl , refl , refl , refl = refl , (refl , (refl , refl))

equalbyPredicateI : ∀{A : Set}{B : A → Set}{bs bs' : Bwd A}{fs fs'}{tot}
                    (TOT : IList B tot)
                    {Bs : IBwd B bs}{Bs' : IBwd B bs'}
                    {Fs : IList B fs}{Fs' : IList B fs'}
                    {h h' : A}
                    {H : B h}{H' : B h'}
                  → (P : {a : A} → B a → Set)
                  → (p : tot ≡ bs <>> (h ∷ fs))
                  → (p' : tot ≡ bs' <>> (h' ∷ fs'))
                  → (q : TOT ≡ subst (IList B) (sym p) (Bs <>>I (H ∷ Fs)))
                  → (q' : TOT ≡ subst (IList B) (sym p') (Bs' <>>I (H' ∷ Fs')))
                  → (ps : IIBwd P Bs)
                  → (ps' : IIBwd P Bs')
                  → (¬PH : ¬(P H))
                  → (¬PH' : ¬(P H'))
                  → Σ (bs ≡ bs') (λ { refl →
                    Σ (h ≡ h')   (λ { refl →
                    Σ (fs ≡ fs') (λ { refl → Bs ≡ Bs' }) }) })
equalbyPredicateI {bs = bs}{bs'}{fs}{fs'}{tot} TOT {Bs} {Bs'} {Fs} {Fs'} {h} {h'} {H} {H'} P refl p' refl q' ps ps' ¬PH ¬PH' with
     equalbyPredicate++I TOT
               P
               (lemma-<>>-++ bs [] (h ∷ fs))
               (trans p' (lemma-<>>-++ bs' [] (h' ∷ fs')))
               ((lemma-<>>I-++I Bs [] (H ∷ Fs)))
               (trans q'
                (trans (cong (subst (IList _) (sym p')) (lemma-<>>I-++I Bs' [] (H' ∷ Fs')))
                 (trans (subst-subst {P = IList _} (sym (lemma-<>>-++ bs' [] (h' ∷ fs'))) {sym p'} {(Bs' <>>I []) ++I (H' ∷ Fs')})
                         (≡-subst-removable (IList _) (trans (sym (lemma-<>>-++ bs' [] (h' ∷ fs'))) (sym p')) (sym (trans p' (lemma-<>>-++ bs' [] (h' ∷ fs')))) _))))
               (IIBwd2IIList refl refl ps)
               (IIBwd2IIList refl refl ps')
               ¬PH
               ¬PH'
... | pbs , snd with <>>[]-cancelʳ bs bs' pbs
equalbyPredicateI TOT {Bs} {Bs'} P p p' q q' ps ps' ¬PH ¬PH'
     | refl , refl , refl , pBs | refl with <>>I[]-cancelʳ Bs Bs' pBs
... | refl = refl , refl , refl , refl