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

open import Prelude.Init; open SetAsType
open import Prelude.ToList
open import Prelude.Decidable

record _//_ (A : Type ) (B : Type ℓ′) {ℓ″} : Type ( ⊔ₗ ℓ′ ⊔ₗ lsuc ℓ″) where
  infix 4 _♯_
  field _♯_ : A  B  Type ℓ″

  _♯?_ :  _ :  {x y}  (x  y)    Decidable² _♯_
  _♯?_ _ _ = dec
open _//_ ⦃...⦄ public

_//^⦅_⦆_ :  (A : Type )  (B : Type ℓ′)  Type _
A //^⦅ ℓ″  B = _//_ A B {ℓ″}

private variable
  X : Type ; Y : Type ℓ′; Z : Type ℓ″
  n : 

-- Unit test to check support for relating types at different levels.
private module _ (X₁ : Type₁) where
  _ :  // X₁
  _ = λ where ._♯_ _  const 

instance
  Apart-List : List X // List X
  Apart-List ._♯_ = Disjoint

  -- Apart-ToList : ⦃ ToList X Y ⦄ → List Y // X
  -- Apart-ToList = toList⇒//ʳ

-- do not expose as instance, as it leads to issues with instance resolution
toList⇒// :  ToList X Y   X // X
toList⇒// ._♯_ x x′ = toList x  toList x′

toList²⇒// :  ToList X Z    ToList Y Z   X // Y
toList²⇒// ._♯_ x x′ = toList x  toList x′

toList⇒//ˡ :  ToList X Y   X // List Y
toList⇒//ˡ ._♯_ x ys = toList x  ys

toList⇒//ʳ :  ToList X Y   List Y // X
toList⇒//ʳ ._♯_ ys x = ys  toList x

mkSym-// :  X //^⦅ ℓ″  Y   Y //^⦅ ℓ″  X
mkSym-//  d  ._♯_ = flip (_♯_  d ⦄)

instance
  Apart-List⁺ : List⁺ X // List⁺ X
  Apart-List⁺ = toList⇒//

  Apart-List⁺ʳ : List X // List⁺ X
  Apart-List⁺ʳ = toList⇒//ʳ

  Apart-List⁺ˡ : List⁺ X // List X
  Apart-List⁺ˡ = toList⇒//ˡ

  Apart-Str = String // String  toList⇒//

  Apart-Vec : Vec X n // Vec X n
  Apart-Vec = toList⇒//

  Apart-Vec⁺ʳ : List X // Vec X n
  Apart-Vec⁺ʳ = toList⇒//ʳ

  Apart-Vec⁺ˡ : Vec X n // List X
  Apart-Vec⁺ˡ = toList⇒//ˡ

  Apart-List⁺-Vec : List⁺ X // Vec X n
  Apart-List⁺-Vec = toList²⇒//

  Apart-Vec-List⁺ : Vec X n // List⁺ X
  Apart-Vec-List⁺ = toList²⇒//