Skip to content

Data.List.Relation.Unary.Linked.Properties

------------------------------------------------------------------------
-- The Agda standard library
--
-- Properties related to Linked
------------------------------------------------------------------------

{-# OPTIONS --cubical-compatible --safe #-}

module Data.List.Relation.Unary.Linked.Properties where

open import Data.Bool.Base using (true; false)
open import Data.List.Base hiding (any)
open import Data.List.Relation.Unary.AllPairs as AllPairs
  using (AllPairs; []; _∷_)
import Data.List.Relation.Unary.AllPairs.Properties as AllPairs
open import Data.List.Relation.Unary.All using (All; []; _∷_)
open import Data.List.Relation.Unary.Linked as Linked
  using (Linked; []; [-]; _∷_)
open import Data.Nat.Base using (zero; suc; _<_; z<s; s<s)
open import Data.Nat.Properties using (≀-refl; m≀n⇒m≀1+n)
open import Data.Maybe.Relation.Binary.Connected
  using (Connected; just; nothing; just-nothing; nothing-just)
open import Level using (Level)
open import Function.Base using (_∘_; flip; _on_)
open import Relation.Binary.Core using (Rel)
open import Relation.Binary.Bundles using (DecSetoid)
open import Relation.Binary.Definitions using (Transitive)
open import Relation.Binary.PropositionalEquality.Core using (_≱_)
open import Relation.Unary using (Pred; Decidable)
open import Relation.Nullary.Decidable using (yes; no; does)

private
  variable
    a b p ℓ : Level
    A : Set a
    B : Set b

------------------------------------------------------------------------
-- Relationship to other predicates
------------------------------------------------------------------------

module _ {R : Rel A ℓ} where

  AllPairs⇒Linked : ∀ {xs} → AllPairs R xs → Linked R xs
  AllPairs⇒Linked []                    = []
  AllPairs⇒Linked (px ∷ [])             = [-]
  AllPairs⇒Linked ((px ∷ _) ∷ py ∷ pxs) =
    px ∷ (AllPairs⇒Linked (py ∷ pxs))

module _ {R : Rel A ℓ} (trans : Transitive R) where

  Linked⇒All : ∀ {v x xs} → R v x →
               Linked R (x ∷ xs) → All (R v) (x ∷ xs)
  Linked⇒All Rvx [-]         = Rvx ∷ []
  Linked⇒All Rvx (Rxy ∷ Rxs) = Rvx ∷ Linked⇒All (trans Rvx Rxy) Rxs

  Linked⇒AllPairs : ∀ {xs} → Linked R xs → AllPairs R xs
  Linked⇒AllPairs []          = []
  Linked⇒AllPairs [-]         = [] ∷ []
  Linked⇒AllPairs (Rxy ∷ Rxs) = Linked⇒All Rxy Rxs ∷ Linked⇒AllPairs Rxs

------------------------------------------------------------------------
-- Introduction (âș) and elimination (⁻) rules for list operations
------------------------------------------------------------------------
-- map

module _ {R : Rel A ℓ} {f : B → A} where

  mapâș : ∀ {xs} → Linked (R on f) xs → Linked R (map f xs)
  mapâș []           = []
  mapâș [-]          = [-]
  mapâș (Rxy ∷ Rxs)  = Rxy ∷ mapâș Rxs

  map⁻ : ∀ {xs} → Linked R (map f xs) → Linked (R on f) xs
  map⁻ {[]}         []           = []
  map⁻ {x ∷ []}     [-]          = [-]
  map⁻ {x ∷ y ∷ xs} (Rxy ∷ Rxs)  = Rxy ∷ map⁻ Rxs

------------------------------------------------------------------------
-- _++_

module _ {R : Rel A ℓ} where

  ++âș : ∀ {xs ys} →
        Linked R xs →
        Connected R (last xs) (head ys) →
        Linked R ys →
        Linked R (xs ++ ys)
  ++âș []          _          Rys         = Rys
  ++âș [-]         _          []          = [-]
  ++âș [-]         (just Rxy) [-]         = Rxy ∷ [-]
  ++âș [-]         (just Rxy) (Ryz ∷ Rys) = Rxy ∷ Ryz ∷ Rys
  ++âș (Rxy ∷ Rxs) Rxsys      Rys         = Rxy ∷ ++âș Rxs Rxsys Rys

------------------------------------------------------------------------
-- applyUpTo

module _ {R : Rel A ℓ} where

  applyUpToâș₁ : ∀ f n → (∀ {i} → suc i < n → R (f i) (f (suc i))) →
                Linked R (applyUpTo f n)
  applyUpToâș₁ f 0               Rf = []
  applyUpToâș₁ f 1               Rf = [-]
  applyUpToâș₁ f (suc n@(suc _)) Rf =
    Rf (s<s z<s) ∷ (applyUpToâș₁ (f ∘ suc) n (Rf ∘ s<s))

  applyUpToâș₂ : ∀ f n → (∀ i → R (f i) (f (suc i))) →
                Linked R (applyUpTo f n)
  applyUpToâș₂ f n Rf = applyUpToâș₁ f n (λ _ → Rf _)

------------------------------------------------------------------------
-- applyDownFrom

module _ {R : Rel A ℓ} where

  applyDownFromâș₁ : ∀ f n → (∀ {i} → suc i < n → R (f (suc i)) (f i)) →
                    Linked R (applyDownFrom f n)
  applyDownFromâș₁ f 0               Rf = []
  applyDownFromâș₁ f 1               Rf = [-]
  applyDownFromâș₁ f (suc n@(suc _)) Rf =
    Rf ≀-refl ∷ applyDownFromâș₁ f n (Rf ∘ m≀n⇒m≀1+n)

  applyDownFromâș₂ : ∀ f n → (∀ i → R (f (suc i)) (f i)) →
                    Linked R (applyDownFrom f n)
  applyDownFromâș₂ f n Rf = applyDownFromâș₁ f n (λ _ → Rf _)

------------------------------------------------------------------------
-- filter

module _ {P : Pred A p} (P? : Decidable P)
         {R : Rel A ℓ} (trans : Transitive R)
         where

  ∷-filterâș : ∀ {x xs} → Linked R (x ∷ xs) → Linked R (x ∷ filter P? xs)
  ∷-filterâș [-] = [-]
  ∷-filterâș {xs = y ∷ _} (r ∷ [-]) with does (P? y)
  ... | false = [-]
  ... | true  = r ∷ [-]
  ∷-filterâș {x = x} {xs = y ∷ ys} (r ∷ râ€Č ∷ rs)
    with does (P? y) | ∷-filterâș {xs = ys} | ∷-filterâș (râ€Č ∷ rs)
  ... | false | ihf | _   = ihf (trans r râ€Č ∷ rs)
  ... | true  | _   | iht = r ∷ iht

  filterâș   : ∀ {xs} → Linked R xs → Linked R (filter P? xs)
  filterâș [] = []
  filterâș {xs = x ∷ []} [-] with does (P? x)
  ... | false = []
  ... | true  = [-]
  filterâș {xs = x ∷ _} (r ∷ rs) with does (P? x)
  ... | false = filterâș rs
  ... | true  = ∷-filterâș (r ∷ rs)