module Haskell.Extra.Erase where
open import Agda.Primitive
open import Agda.Builtin.Sigma
open import Agda.Builtin.Equality
open import Haskell.Prim
open import Haskell.Prim.List
open import Haskell.Extra.Refinement
open import Haskell.Law.Equality
private variable
@0 x y : a
@0 xs : List a
record Erase (@0 a : Type ℓ) : Type ℓ where
instance constructor iErased
field @0 {{get}} : a
open Erase public
{-# COMPILE AGDA2HS Erase tuple #-}
pattern Erased x = iErased {{x}}
infixr 4 ⟨_⟩_
record Σ0 (@0 a : Type) (b : @0 a → Type) : Type where
constructor ⟨_⟩_
field
@0 proj₁ : a
proj₂ : b proj₁
open Σ0 public
{-# COMPILE AGDA2HS Σ0 unboxed #-}
pattern <_> x = record { proj₁ = _ ; proj₂ = x }
Singleton : (@0 x : a) → Type
Singleton x = ∃ _ (x ≡_)
{-# COMPILE AGDA2HS Singleton inline #-}
pattern sing x = x ⟨ refl ⟩
instance
sing-id : {x : a} → Singleton x
sing-id = sing _
{-# COMPILE AGDA2HS sing-id inline #-}
singCong : {@0 a : Type} {@0 x : a} (f : a → b) → Singleton x → Singleton (f x)
singCong f (x ⟨ p ⟩) = f x ⟨ cong f p ⟩
{-# COMPILE AGDA2HS singCong inline #-}
singCong2 : (f : a → b → c) → Singleton x → Singleton y → Singleton (f x y)
singCong2 f (x ⟨ p ⟩) (y ⟨ q ⟩) = f x y ⟨ cong₂ f p q ⟩
{-# COMPILE AGDA2HS singCong2 inline #-}
singHead : Singleton (x ∷ xs) → Singleton x
singHead {x = x} (ys ⟨ p ⟩) =
head ys
⟨ subst (λ ys → ⦃ @0 _ : NonEmpty ys ⦄ → x ≡ head ys)
p refl ⟩
where instance @0 ne : NonEmpty ys
ne = subst NonEmpty p itsNonEmpty
{-# COMPILE AGDA2HS singHead inline #-}
singTail : Singleton (x ∷ xs) → Singleton xs
singTail {xs = xs} (ys ⟨ p ⟩) =
tail ys
⟨ subst (λ ys → ⦃ @0 _ : NonEmpty ys ⦄ → xs ≡ tail ys)
p refl ⟩
where instance @0 ne : NonEmpty ys
ne = subst NonEmpty p itsNonEmpty
{-# COMPILE AGDA2HS singTail inline #-}
singErase : {@0 a : Type} {@0 x : a} → Singleton (Erased x)
singErase {x = x} = Erased x ⟨ refl ⟩
{-# COMPILE AGDA2HS singErase inline #-}
erase-injective : Erased x ≡ Erased y → x ≡ y
erase-injective refl = refl
inspect_by_ : (x : a) → (Singleton x → b) → b
inspect x by f = f (sing x)