Source code on Github
{-# OPTIONS --safe #-}
module Prelude.Closures where

open import Prelude.Init; open SetAsType
open import Prelude.General hiding (_⊢_)
open import Prelude.Setoid
open import Prelude.Decidable
open import Prelude.Bifunctor

-- labelled relations
LRel : Type  × Type  (ℓ′ : Level)  Type ( ⊔ₗ lsuc ℓ′)
LRel (A , L)  = A  L  A  Type 

LRel₀ : Type  × Type  Type _
LRel₀ (A , L) = LRel (A , L) 0ℓ

private variable
  A : Type 
  L : Type

unlabel : LRel (A , L) ℓ′  Rel A ℓ′
unlabel _—→[_]_ x y =  λ α  x —→[ α ] y

infix 0 emitting_∶_ emit∶_
-- pattern emitting_∶_ = _,_

emitting_∶_ :  {B : Pred A ℓ′}  (x : A)  B x  Σ A B
emitting_∶_ = _,_
emit∶_ = -,_

-- transitive operations
TransitiveOp : Rel A   Type _
TransitiveOp _~_ =  x {y z}  x ~ y  y ~ z  x ~ z

mkTransitiveOp :  {_~_ : Rel A }  Transitive _~_  TransitiveOp _~_
mkTransitiveOp trans _ = trans

-- [RECOMMENDED] infix -1 _—→_

module LabelledReflexiveTransitiveClosure
  {A : Type } {L : Type} (_—[_]→_ : LRel (A , L) ) where

  private
    variable
      x y z : A
      α α′ : L
      αs αs′ : List L

  -- left-biased
  infix  3 _∎
  infixr 2 _—→⟨_⟩_
  infix  1 begin_; pattern begin_ x = x
  infix -1 _—→_ _—[_]↠_ _—↠_ _—[_]↠⁺_ _—↠⁺_
  data _—[_]↠_ : LRel (A , List L)  where
    _∎ :  x  x —[ [] ]↠ x
    _—→⟨_⟩_ :  x  x —[ α ]→ y  y —[ αs ]↠ z  x —[ α  αs ]↠ z
  data _—[_]↠⁺_ : LRel (A , List L)  where
    _—→⟨_⟩_ :  x  x —[ α ]→ y  y —[ αs ]↠ z  x —[ α  αs ]↠⁺ z

  _—→_  = unlabel _—[_]→_
  _—↠_  = unlabel _—[_]↠_
  _—↠⁺_ = unlabel _—[_]↠⁺_

  -- transitivity of _—↠⁽⁺⁾_
  —↠-trans : Transitive _—↠_
  —↠-trans ([]     , (x ))     xz = xz
  —↠-trans (_  αs , (_ —→⟨ r  xy)) yz = -, (_ —→⟨ r  —↠-trans (αs , xy) yz .proj₂)

  ↠⁺⇒↠ : _—↠⁺_ ⇒² _—↠_
  ↠⁺⇒↠ (_ , (_ —→⟨ r  xy)) = -, (_ —→⟨ r  xy)

  —↠⁺-transˡ : Trans _—↠⁺_ _—↠_ _—↠⁺_
  —↠⁺-transˡ (_ , (_ —→⟨ r  xy)) yz = -, (_ —→⟨ r  —↠-trans (-, xy) yz .proj₂)

  —↠⁺-transʳ : Trans _—↠_ _—↠⁺_ _—↠⁺_
  —↠⁺-transʳ (_ , (_ )) yz⁺ = yz⁺
  —↠⁺-transʳ (_ , (_ —→⟨ r  xy)) yz⁺ = -, (_ —→⟨ r  —↠-trans (-, xy) (↠⁺⇒↠ yz⁺) .proj₂)

  —↠⁺-trans : Transitive _—↠⁺_
  —↠⁺-trans = —↠⁺-transʳ  ↠⁺⇒↠

  _—↠⟨_⟩_  = TransitiveOp _—↠_   mkTransitiveOp —↠-trans
  _—↠⁺⟨_⟩_ = TransitiveOp _—↠⁺_  mkTransitiveOp —↠⁺-trans

  -- right-biased view
  _←[_]—_ : LRel (A , L) 
  y ←[ α ]— x = x —[ α ]→ y

  -- infix  3 _∎
  infixr 2 _⟨_⟩←—_
  infix -1 _←—_ _↞[_]—_ _↞—_ _⁺↞[_]—_ _⁺↞—_
  data _↞[_]—_ : LRel (A , List L)  where
    _∎ :  x  x ↞[ [] ]— x
    _⟨_⟩←—_ :  z  (z ←[ α ]— y)  (y ↞[ αs ]— x)  z ↞[ αs L.∷ʳ α ]— x
  data _⁺↞[_]—_ : LRel (A , List L)  where
    _⟨_⟩←—_ :  z  (z ←[ α ]— y)  (y ↞[ αs ]— x)  z ⁺↞[ αs L.∷ʳ α ]— x

  _←—_  = unlabel _←[_]—_
  _↞—_  = unlabel _↞[_]—_
  _⁺↞—_ = unlabel _⁺↞[_]—_

  -- view correspondence
  infixr 2 _`—→⟨_⟩_
  _`—→⟨_⟩_ :  x  y ←[ α ]— x  z ↞[ αs ]— y  z ↞[ α  αs ]— x
  _ `—→⟨ st  _            = _  st ⟩←— _ 
  _ `—→⟨ st  _  st′ ⟩←— p = _  st′ ⟩←— _ `—→⟨ st  p

  viewLeft : x —[ αs ]↠ y  y ↞[ αs ]— x
  viewLeft (_ )          = _ 
  viewLeft (_ —→⟨ st  p) = _ `—→⟨ st  viewLeft p

  viewLeft∃ : x —↠ y  y ↞— x
  viewLeft∃ (_ , xy) = -, viewLeft xy

  infixr 2 _`⟨_⟩←—_
  _`⟨_⟩←—_ :  z  y —[ α ]→ z  x —[ αs ]↠ y  x —[ αs ∷ʳ α ]↠ z
  _ `⟨ st ⟩←— (_ )           = _ —→⟨ st  _ 
  _ `⟨ st ⟩←— (_ —→⟨ st′  p) = _ —→⟨ st′  (_ `⟨ st ⟩←— p)

  viewRight : y ↞[ αs ]— x  x —[ αs ]↠ y
  viewRight (_ )          = _ 
  viewRight (_  st ⟩←— p) = _ `⟨ st ⟩←— viewRight p

  view↔ : (x —[ αs ]↠ y)  (y ↞[ αs ]— x)
  view↔ = viewLeft , viewRight

  -- view correspondence between _—↠⁺_ and _⁺↞—_
  infixr 2 _`—→⁺⟨_⟩_
  _`—→⁺⟨_⟩_ :  x  y ←[ α ]— x  z ↞[ αs ]— y  z ⁺↞[ α  αs ]— x
  _ `—→⁺⟨ st  _            = _  st ⟩←— _ 
  _ `—→⁺⟨ st  _  st′ ⟩←— p = _  st′ ⟩←— _ `—→⟨ st  p

  viewLeft⁺ : x —[ αs ]↠⁺ y  y ⁺↞[ αs ]— x
  viewLeft⁺ (_ —→⟨ st  p) = _ `—→⁺⟨ st  viewLeft p

  infixr 2 _`⟨_⟩⁺←—_
  _`⟨_⟩⁺←—_ :  z  y —[ α ]→ z  x —[ αs ]↠ y  x —[ αs ∷ʳ α ]↠⁺ z
  _ `⟨ st ⟩⁺←— (_ )           = _ —→⟨ st  _ 
  _ `⟨ st ⟩⁺←— (_ —→⟨ st′  p) = _ —→⟨ st′  (_ `⟨ st ⟩←— p)

  viewRight⁺ : y ⁺↞[ αs ]— x  x —[ αs ]↠⁺ y
  viewRight⁺ (_  st ⟩←— p) = _ `⟨ st ⟩⁺←— viewRight p

  view↔⁺ : (x —[ αs ]↠⁺ y)  (y ⁺↞[ αs ]— x)
  view↔⁺ = viewLeft⁺ , viewRight⁺

  -- transitivity of _↞—⁽⁺⁾_
  ↞—-trans : Transitive _↞—_
  ↞—-trans zy yx = viewLeft <$>₂′ —↠-trans (viewRight <$>₂′ yx) (viewRight <$>₂′ zy)

  ↞⁺⇒↞ : _⁺↞—_ ⇒² _↞—_
  ↞⁺⇒↞ = map₂′ viewLeft  ↠⁺⇒↠  map₂′ viewRight⁺

  ⁺↞—-transˡ : Trans _⁺↞—_ _↞—_ _⁺↞—_
  ⁺↞—-transˡ zy⁺ yx = viewLeft⁺ <$>₂′ —↠⁺-transʳ (viewRight <$>₂′ yx) (viewRight⁺ <$>₂′ zy⁺)

  ⁺↞—-transʳ : Trans _↞—_ _⁺↞—_ _⁺↞—_
  ⁺↞—-transʳ zy yx⁺ = viewLeft⁺ <$>₂′ —↠⁺-transˡ (viewRight⁺ <$>₂′ yx⁺) (viewRight <$>₂′ zy)

  ⁺↞—-trans : Transitive _⁺↞—_
  ⁺↞—-trans = ⁺↞—-transʳ  ↞⁺⇒↞

  _↞—⟨_⟩_  = TransitiveOp _↞—_   mkTransitiveOp ↞—-trans
  _⁺↞—⟨_⟩_ = TransitiveOp _⁺↞—_  mkTransitiveOp ⁺↞—-trans

-- [BUG] this needs to be placed above the simpler `ReflexiveTransitiveClosure`:
-- Agda complains that we're re-definining `_—→⟨_⟩_`, although they should leave in different namespaces.
module UpToLabelledReflexiveTransitiveClosure
  {A : Type } {L : Type} (_—[_]→_ : LRel (A , L) )  _ : ISetoid A  where

  open LabelledReflexiveTransitiveClosure _—[_]→_ public
    using (_—→_; _←[_]—_; _←—_)

  private
    ℓ⊔ℓ′ =  ⊔ₗ relℓ
    variable
      x y z x′ y′ z′ : A
      α α′ : L
      αs αs′ : List L

  -- left-biased
  infix  3 _∎
  infixr 2 _—→⟨_⟩_⊢_
  infix  1 begin_; pattern begin_ x = x
  infix -1 _—↠_ _—[_]↠_ _—↠⁺_ _—[_]↠⁺_
  data _—[_]↠_ : LRel (A , List L) ℓ⊔ℓ′ where
    _∎ :  x  x —[ [] ]↠ x
    _—→⟨_⟩_⊢_ :  x {x′ y y′ z}
       x′ —[ α ]→ y′
       x  x′ × y  y′
       y —[ αs ]↠ z
        --———————————————
       x —[ α  αs ]↠ z
  data _—[_]↠⁺_ : LRel (A , List L) ℓ⊔ℓ′ where
    _—→⟨_⟩_⊢_ :  x {x′ y y′ z}
       x′ —[ α ]→ y′
       x  x′ × y  y′
       y —[ αs ]↠ z
        --———————————————
       x —[ α  αs ]↠⁺ z
  _—↠_  = unlabel _—[_]↠_
  _—↠⁺_ = unlabel _—[_]↠⁺_

  -- right-biased view
  -- infix  3 _∎
  infixr 2 _⟨_⟩←—_⊢_
  infix -1 _↞[_]—_ _↞—_ _⁺↞[_]—_ _⁺↞—_
  data _↞[_]—_ : LRel (A , List L) ℓ⊔ℓ′ where
    _∎ :  x  x ↞[ [] ]— x
    _⟨_⟩←—_⊢_ :  z {z′ y y′ x}
       (z′ ←[ α ]— y′)
       z  z′ × y  y′
       (y ↞[ αs ]— x)
        --————————————————————
       z ↞[ αs L.∷ʳ α ]— x
  data _⁺↞[_]—_ : LRel (A , List L) ℓ⊔ℓ′ where
    _⟨_⟩←—_⊢_ :  z {z′ y y′ x}
       (z′ ←[ α ]— y′)
       z  z′ × y  y′
       (y ↞[ αs ]— x)
        --————————————————————
       z ⁺↞[ αs L.∷ʳ α ]— x
  _↞—_  = unlabel _↞[_]—_
  _⁺↞—_ = unlabel _⁺↞[_]—_

  -- automatic-proof version
  module _  _ : DecSetoid A  where

    infixr 2 _—→⟨_⟩_ _⟨_⟩←—_

    _—→⟨_⟩_ :  (x : A)
       x′ —[ α ]→ y′
       y —[ αs ]↠ z
       {True $ x ≈? x′}
       {True $ y ≈? y′}
        --————————————————
       x —[ α  αs ]↠ z
    (x —→⟨ x′→y′  y↠z) {p₁} {p₂} = x —→⟨ x′→y′  toWitness p₁ , toWitness p₂  y↠z

    _⟨_⟩←—_ :  z
       z′ ←[ α ]— y′
       y ↞[ αs ]— x
       {True $ z ≈? z′}
       {True $ y ≈? y′}
        --——————————————————
       z ↞[ αs L.∷ʳ α ]— x
    (z  z′←y′ ⟩←— y↞x) {p₁} {p₂} = z  z′←y′ ⟩←— toWitness p₁ , toWitness p₂  y↞x

  -- view correspondence
  infixr 2 _`—→⟨_⟩_⊢_
  _`—→⟨_⟩_⊢_ :  (x : A) {x′ y y′ x}
     y′ ←[ α ]— x′
     x  x′ × y  y′
     z ↞[ αs ]— y
     z ↞[ α  αs ]— x
  _ `—→⟨ st  eq  _                   = _  st ⟩←— Product.swap eq  _ 
  x `—→⟨ st  eq  _  st′ ⟩←— eq′  tr = _  st′ ⟩←— eq′  (x `—→⟨ st  eq  tr)

  viewLeft : x —[ αs ]↠ y  y ↞[ αs ]— x
  viewLeft (_ )          = _ 
  viewLeft (c —→⟨ st  eq  p) = c `—→⟨ st  eq  viewLeft p

  infixr 2 _`⟨_⟩←—_⊢_
  _`⟨_⟩←—_⊢_ :  z {z′ y y′ x}
     y′ —[ α ]→ z′
     z  z′ × y  y′
     x —[ αs ]↠ y
     x —[ αs ∷ʳ α ]↠ z
  _ `⟨ st ⟩←— eq  (_ )                 = _ —→⟨ st  Product.swap eq  _ 
  _ `⟨ st ⟩←— eq  (_ —→⟨ st′  eq′  p) = _ —→⟨ st′  eq′  (_ `⟨ st ⟩←— eq  p)

  viewRight : y ↞[ αs ]— x  x —[ αs ]↠ y
  viewRight (_ )          = _ 
  viewRight (_  st ⟩←— eq  p) = _ `⟨ st ⟩←— eq  viewRight p

  view↔ : (x —[ αs ]↠ y)  (y ↞[ αs ]— x)
  view↔ = viewLeft , viewRight

module ReflexiveTransitiveClosure {A : Type } (_—→_ : Rel A ) where

  private variable x y z : A

  -- left-biased
  infix  3 _∎
  infixr 2 _—→⟨_⟩_ _—↠⟨_⟩_
  infix  1 begin_; pattern begin_ x = x
  infix -1 _—↠_ _—↠⁺_
  data _—↠_ : Rel A  where
    _∎ :  x  x —↠ x
    _—→⟨_⟩_ :  x  x —→ y  y —↠ z  x —↠ z
  data _—↠⁺_ : Rel A  where
    _—→⟨_⟩_ :  x  x —→ y  y —↠ z  x —↠⁺ z

  —↠-trans : Transitive _—↠_
  —↠-trans (x ) xz = xz
  —↠-trans (_ —→⟨ r  xy) yz = _ —→⟨ r  —↠-trans xy yz

  _—↠⟨_⟩_ :  x  x —↠ y  y —↠ z  x —↠ z
  _—↠⟨_⟩_ _ = —↠-trans

  -- right-biased view
  _←—_ = flip _—→_

  -- infix  3 _∎
  infixr 2 _⟨_⟩←—_
  infix -1 _←—_ _↞—_ _⁺↞—_
  data _↞—_ : Rel A  where
    _∎ :  x  x ↞— x
    _⟨_⟩←—_ :  z  z ←— y  y ↞— x  z ↞— x
  data _⁺↞—_ : Rel A  where
    _⟨_⟩←—_ :  z  z ←— y  y ↞— x  z ⁺↞— x

  ↞—-trans : Transitive _↞—_
  ↞—-trans (x ) xz = xz
  ↞—-trans (_  r ⟩←— zy) yx = _  r ⟩←— ↞—-trans zy yx

  _⟨_⟩↞—_ :  z  z ↞— y  y ↞— x  z ↞— x
  _⟨_⟩↞—_ _ = ↞—-trans

  -- view correspondence
  infixr 2 _`—→⟨_⟩_
  _`—→⟨_⟩_ :  x  y ←— x  z ↞— y  z ↞— x
  _ `—→⟨ st  _            = _  st ⟩←— _ 
  _ `—→⟨ st  _  st′ ⟩←— p = _  st′ ⟩←— _ `—→⟨ st  p

  viewLeft : x —↠ y  y ↞— x
  viewLeft (_ )          = _ 
  viewLeft (_ —→⟨ st  p) = _ `—→⟨ st  viewLeft p

  infixr 2 _`⟨_⟩←—_
  _`⟨_⟩←—_ :  z  y —→ z  x —↠ y  x —↠ z
  _ `⟨ st ⟩←— (_ )           = _ —→⟨ st  _ 
  _ `⟨ st ⟩←— (_ —→⟨ st′  p) = _ —→⟨ st′  (_ `⟨ st ⟩←— p)

  viewRight : y ↞— x  x —↠ y
  viewRight (_ )          = _ 
  viewRight (_  st ⟩←— p) = _ `⟨ st ⟩←— viewRight p

  view↔ : (x —↠ y)  (y ↞— x)
  view↔ = viewLeft , viewRight

module UpToReflexiveTransitiveClosure
  {A : Type } (_—→_ : Rel A )  _ : ISetoid A  where

  open ReflexiveTransitiveClosure _—→_ public
    using (_←—_)

  private
    ℓ⊔ℓ′ =  ⊔ₗ relℓ
    variable x y z x′ y′ z′ : A

  -- left-biased
  infix  3 _∎
  infixr 2 _—→⟨_⟩_⊢_
  infix  1 begin_; pattern begin_ x = x
  infix -1 _—↠_ _—↠⁺_
  data _—↠_ : Rel A ℓ⊔ℓ′ where
    _∎ :  x  x —↠ x
    _—→⟨_⟩_⊢_ :  x {x′ y y′ z}
       x′ —→ y′
       x  x′ × y  y′
       y —↠ z
        --———————————————
       x —↠ z
  data _—↠⁺_ : Rel A ℓ⊔ℓ′ where
    _—→⟨_⟩_⊢_ :  x {x′ y y′ z}
       x′ —→ y′
       x  x′ × y  y′
       y —↠ z
        --———————————————
       x —↠⁺ z

  -- transitivity of _—↠⁽⁺⁾_
  —↠-trans : Transitive _—↠_
  —↠-trans (x ) xz = xz
  —↠-trans (_ —→⟨ r  p  xy) yz = _ —→⟨ r  p  —↠-trans xy yz

  ↠⁺⇒↠ : _—↠⁺_ ⇒² _—↠_
  ↠⁺⇒↠ (_ —→⟨ r  p  xy) = _ —→⟨ r  p  xy

  —↠⁺-transˡ : Trans _—↠⁺_ _—↠_ _—↠⁺_
  —↠⁺-transˡ (_ —→⟨ r  p  xy) yz = _ —→⟨ r  p  —↠-trans xy yz

  —↠⁺-transʳ : Trans _—↠_ _—↠⁺_ _—↠⁺_
  —↠⁺-transʳ (_ ) yz⁺ = yz⁺
  —↠⁺-transʳ (_ —→⟨ r  p  xy) yz⁺ = _ —→⟨ r  p  —↠-trans xy (↠⁺⇒↠ yz⁺)

  —↠⁺-trans : Transitive _—↠⁺_
  —↠⁺-trans = —↠⁺-transʳ  ↠⁺⇒↠

  _—↠⟨_⟩_  = TransitiveOp _—↠_   mkTransitiveOp —↠-trans
  _—↠⁺⟨_⟩_ = TransitiveOp _—↠⁺_  mkTransitiveOp —↠⁺-trans

  -- right-biased view
  -- infix  3 _∎
  infixr 2 _⟨_⟩←—_⊢_
  infix -1 _↞—_ _⁺↞—_
  data _↞—_ : Rel A ℓ⊔ℓ′ where
    _∎ :  x  x ↞— x
    _⟨_⟩←—_⊢_ :  z {z′ y y′ x}
       (z′ ←— y′)
       z  z′ × y  y′
       (y ↞— x)
        --————————————————————
       z ↞— x
  data _⁺↞—_ : Rel A ℓ⊔ℓ′ where
    _⟨_⟩←—_⊢_ :  z {z′ y y′ x}
       (z′ ←— y′)
       z  z′ × y  y′
       (y ↞— x)
        --————————————————————
       z ⁺↞— x

  -- transitivity of _⁽⁺⁾↞—_
  ↞—-trans : Transitive _↞—_
  ↞—-trans (x ) xz = xz
  ↞—-trans (_  r ⟩←— p  xy) yz = _  r ⟩←— p  ↞—-trans xy yz

  ↞⁺⇒↞ : _⁺↞—_ ⇒² _↞—_
  ↞⁺⇒↞ (_  r ⟩←— p  xy) = _  r ⟩←— p  xy

  ⁺↞—-transˡ : Trans _⁺↞—_ _↞—_ _⁺↞—_
  ⁺↞—-transˡ (_  r ⟩←— p  xy) yz = _  r ⟩←— p  ↞—-trans xy yz

  ⁺↞—-transʳ : Trans _↞—_ _⁺↞—_ _⁺↞—_
  ⁺↞—-transʳ (_ ) yz⁺ = yz⁺
  ⁺↞—-transʳ (_  r ⟩←— p  xy) yz⁺ = _  r ⟩←— p  ↞—-trans xy (↞⁺⇒↞ yz⁺)

  ⁺↞—-trans : Transitive _⁺↞—_
  ⁺↞—-trans = ⁺↞—-transʳ  ↞⁺⇒↞

  _↞—⟨_⟩_  = TransitiveOp _↞—_   mkTransitiveOp ↞—-trans
  _⁺↞—⟨_⟩_ = TransitiveOp _⁺↞—_  mkTransitiveOp ⁺↞—-trans

  -- automatic-proof version
  module _  ds : DecSetoid A  where

    infixr 2 _—→⟨_⟩_ _⟨_⟩←—_

    _—→⟨_⟩_ :  x
       x′ —→ y′
       y —↠ z
       {True $ x ≈? x′}
       {True $ y ≈? y′}
        --————————————————
       x —↠ z
    (x —→⟨ x′→y′  y↠z) {p₁} {p₂} = x —→⟨ x′→y′  toWitness p₁ , toWitness p₂  y↠z

    _⟨_⟩←—_ :  z
       z′ ←— y′
       y ↞— x
       {True $ z ≈? z′}
       {True $ y ≈? y′}
        --——————————————————
       z ↞— x
    (z  z′←y′ ⟩←— y↞x) {p₁} {p₂} = z  z′←y′ ⟩←— toWitness p₁ , toWitness p₂  y↞x

  -- view correspondence
  infixr 2 _`—→⟨_⟩_⊢_
  _`—→⟨_⟩_⊢_ :  (x : A) {x′ y y′ x}
     y′ ←— x′
     x  x′ × y  y′
     z ↞— y
     z ↞— x
  _ `—→⟨ st  eq  _                   = _  st ⟩←— Product.swap eq  _ 
  x `—→⟨ st  eq  _  st′ ⟩←— eq′  tr = _  st′ ⟩←— eq′  (x `—→⟨ st  eq  tr)

  viewLeft : x —↠ y  y ↞— x
  viewLeft (_ )          = _ 
  viewLeft (c —→⟨ st  eq  p) = c `—→⟨ st  eq  viewLeft p

  infixr 2 _`⟨_⟩←—_⊢_
  _`⟨_⟩←—_⊢_ :  z {z′ y y′ x}
     y′ —→ z′
     z  z′ × y  y′
     x —↠ y
     x —↠ z
  _ `⟨ st ⟩←— eq  (_ )                 = _ —→⟨ st  Product.swap eq  _ 
  _ `⟨ st ⟩←— eq  (_ —→⟨ st′  eq′  p) = _ —→⟨ st′  eq′  (_ `⟨ st ⟩←— eq  p)

  viewRight : y ↞— x  x —↠ y
  viewRight (_ )          = _ 
  viewRight (_  st ⟩←— eq  p) = _ `⟨ st ⟩←— eq  viewRight p

  view↔ : (x —↠ y)  (y ↞— x)
  view↔ = viewLeft , viewRight

private
  open import Prelude.Nary
  variable n : 

  module _ where

    infix -1 _—→_
    data _—→_ : Rel₀  where
      [inc] : n —→ suc n
      [dec] : suc n —→ n

    open ReflexiveTransitiveClosure _—→_

    _ : 10 —↠ 10
    _ = begin 10 

    _ : 10 —↠⁺ 12
    _ = begin
      10 —→⟨ [inc] 
      11 —→⟨ [dec] 
      10 —→⟨ [inc] 
      11 —→⟨ [inc] 
      12 

    _ : 12 ⁺↞— 10
    _ = begin
      12  [inc] ⟩←—
      11  [inc] ⟩←—
      10  [dec] ⟩←—
      11  [inc] ⟩←—
      10 

  -- module _ where

  --   infix -1 _—[_]→_
  --   data _—[_]→_ : LRel₀ (ℕ , String) where
  --     [inc] : n —[ "inc" ]→ suc n
  --     [dec] : suc n —[ "dec" ]→ n

  --   open LabelledReflexiveTransitiveClosure _—[_]→_

  --   _ : 10 —[ [] ]↠ 10
  --   _ = begin 10 ∎

  --   _ : 10 —↠ 10
  --   _ = emit∶ begin 10 ∎

  --   _ : 10 —↠ 10
  --   _ = emitting [] ∶ begin 10 ∎

  --   _ : 10 —↠⁺ 12
  --   _ = emitting ⟦ "inc" , "dec" , "inc" , "inc" ⟧ ∶
  --       begin 10 —→⟨ [inc] ⟩
  --             11 —→⟨ [dec] ⟩
  --             10 —→⟨ [inc] ⟩
  --             11 —→⟨ [inc] ⟩
  --             12 ∎

  --   _ : 12 ⁺↞— 10
  --   _ = emitting ⟦ "inc" , "dec" , "inc" , "inc" ⟧ ∶
  --       begin 12 ⟨ [inc] ⟩←—
  --             11 ⟨ [inc] ⟩←—
  --             10 ⟨ [dec] ⟩←—
  --             11 ⟨ [inc] ⟩←—
  --             10 ∎

  module _ where

    infix -1 _—[_]→_
    data _—[_]→_ : LRel₀ ( , String) where
      [inc] : n —[ "inc" ]→ suc n
      [dec] : suc n —[ "dec" ]→ n

    instance
      Setoidℕ : ISetoid 
      Setoidℕ = λ where
        .relℓ  _
        ._≈_   _≡_

    open import Prelude.DecEq.Core
    open UpToLabelledReflexiveTransitiveClosure _—[_]→_

    _ : 10 —[ [] ]↠ 10
    _ = begin 10 

    _ : 10 —↠ 10
    _ = emit∶ begin 10 

    _ : 10 —↠ 10
    _ = emitting []  begin 10 

    _ : 10 —↠⁺ 12
    _ = emitting  "inc" , "dec" , "inc" , "inc"  
        begin 10 —→⟨ [inc]       it , it 
              11 —→⟨ [dec] {10} 
              10 —→⟨ [inc] {10} 
              11 —→⟨ [inc] {11} 
              12 
              -- [BUG] cannot replace with begin 10 —→⟨ [inc] ⟩ 11 ⋯
              -- i.e. unnecessary implicits + first two equivalence proofs

    _ : 12 ⁺↞— 10
    _ = emitting  "inc" , "dec" , "inc" , "inc"  
        begin 12  [inc]      ⟩←— it , it 
              11  [inc] {10} ⟩←—
              10  [dec] {10} ⟩←—
              11  [inc] {10} ⟩←—
              10