Properties

------------------------------------------------------------------------
-- The Agda standard library
--
-- Properties of operations on DiffList
------------------------------------------------------------------------

{-# OPTIONS --without-K --safe #-}

module Data.DifferenceList.Properties where

open import Data.DifferenceList.Base
  using (DiffList; fromList; toList; viaList; []; _∷_; [_]; _++_; _∷ʳ_; map)
open import Data.List.Base as List using (List)
open import Data.List.Properties using (++-assoc; ++-identityʳ)
open import Data.Product.Base using (Σ; _,_)
open import Function.Base using (_∘′_; id; flip)
open import Level using (Level)
open import Relation.Binary.PropositionalEquality
  using (_≡_; refl; cong; _≗_; module ≡-Reasoning)

open ≡-Reasoning

private
  variable
    a b : Level
    A : Set a
    B : Set b
    xs ys : List A
    dxs dys : DiffList A


------------------------------------------------------------------------
-- Relation between Lists and equivalent DiffLists

infix 4 _∼_
_∼_ : List A → DiffList A → Set _
xs ∼ dxs = fromList xs ≗ dxs

ListLike : DiffList A → Set _
ListLike {A = A} dxs = Σ (List A) (_∼ dxs)

------------------------------------------------------------------------
-- Properties of fromList and toList

∼-fromList : xs ∼ fromList xs
∼-fromList _ = refl

toList∘fromList : (xs : List A) → toList (fromList xs) ≡ xs
toList∘fromList = ++-identityʳ

toList⁺ : xs ∼ dxs → xs ≡ toList dxs
toList⁺ {xs = xs} {dxs} xs∼dxs = begin
  xs                    ≡⟨ toList∘fromList xs ⟨
  toList (fromList xs)  ≡⟨ xs∼dxs List.[] ⟩
  toList dxs            ∎

fromList-++ : (xs ys : List A) →
              fromList (xs List.++ ys) ≗ fromList xs ++ fromList ys
fromList-++ = ++-assoc

toList-++ : ListLike dxs → (dys : DiffList A) →
            toList dxs List.++ toList dys ≡ toList (dxs ++ dys)
toList-++ {dxs = dxs} (xs , xs∼dxs) dys = begin
  toList dxs List.++ toList dys  ≡⟨ cong (List._++ toList dys) (toList⁺ xs∼dxs) ⟨
  xs List.++ toList dys          ≡⟨⟩
  fromList xs (toList dys)       ≡⟨ xs∼dxs (toList dys) ⟩
  dxs (toList dys)               ≡⟨⟩
  toList (dxs ++ dys)            ∎

viaList⁺ : (f : List A → List B) → xs ∼ dxs → f xs ∼ viaList f dxs
viaList⁺ {xs = xs} {dxs = dxs} f xs∼dxs k = begin
  fromList (f xs)           k  ≡⟨ cong (flip fromList _ ∘′ f) (toList⁺ xs∼dxs) ⟩
  fromList (f (toList dxs)) k  ≡⟨⟩
  viaList f dxs             k  ∎

------------------------------------------------------------------------
-- Properties of operations that preserve _∼_

[]⁺ : List.[] {A = A} ∼ []
[]⁺ _ = refl

[_]⁺ : (x : A) → List.[ x ] ∼ [ x ]
[_]⁺ _ _ = refl

++⁺ : xs ∼ dxs → ys ∼ dys → xs List.++ ys ∼ dxs ++ dys
++⁺ {xs = xs} {dxs = dxs} {ys = ys} {dys = dys} xs∼dxs ys∼dys k = begin
  fromList (xs List.++ ys) k      ≡⟨ fromList-++ xs ys k ⟩
  (fromList xs ++ fromList ys) k  ≡⟨⟩
  fromList xs (fromList ys k)     ≡⟨ cong (fromList xs) (ys∼dys k) ⟩
  fromList xs (dys k)             ≡⟨ xs∼dxs (dys k) ⟩
  dxs (dys k)                     ≡⟨⟩
  (dxs ++ dys) k                  ∎

∷⁺ : (x : A) → xs ∼ dxs → x List.∷ xs ∼ x ∷ dxs
∷⁺ x = ++⁺ [ x ]⁺

∷ʳ⁺ : (x : A) → xs ∼ dxs → xs List.∷ʳ x ∼ dxs ∷ʳ x
∷ʳ⁺ x xs∼dxs = ++⁺ xs∼dxs [ x ]⁺

map⁺ : (f : A → B) → xs ∼ dxs → List.map f xs ∼ map f dxs
map⁺ f = viaList⁺ _