PLFA agda exercises
module DaraisPhoas where

open import Agda.Primitive using (_āŠ”_)

module Prelude where

  infixr 3 āˆƒš‘ š‘”
  infixl 5 _∨_
  infixr 20 _∷_

  data š”¹ : Set where
    T : š”¹
    F : š”¹

  data _∨_ {ℓ₁ ā„“ā‚‚} (A : Set ℓ₁) (B : Set ā„“ā‚‚) : Set (ℓ₁ āŠ” ā„“ā‚‚) where
    Inl : A → A ∨ B
    Inr : B → A ∨ B

  syntax āˆƒš‘ š‘” A (Ī» x → B) = ∃ x ⦂ A š‘ š‘” B
  data āˆƒš‘ š‘” {ℓ₁ ā„“ā‚‚} (A : Set ℓ₁) (B : A → Set ā„“ā‚‚) : Set (ℓ₁ āŠ” ā„“ā‚‚) where
    ⟨∃_,_⟩ : āˆ€ (x : A) → B x → ∃ x ⦂ A š‘ š‘” B x

  data ⟬_⟭ {ā„“} (A : Set ā„“) : Set ā„“ where
    [] : ⟬ A ⟭
    _∷_ : A → ⟬ A ⟭ → ⟬ A ⟭

open Prelude

infixr 15 _āŸØā†’āŸ©_
data type : Set where
  āŸØā„•āŸ©   : type
  _āŸØā†’āŸ©_ : type → type → type

infixl 15 _āŸØāˆ™āŸ©_
data exp-phoas (var : type → ⟬ type ⟭ → Set) : āˆ€ (Ī“ : ⟬ type ⟭) (Ļ„ : type) → Set where
  Var : āˆ€ {Ī“ Ļ„}
    (x : var Ļ„ Ī“)
    → exp-phoas var Ī“ Ļ„
  ⟨λ⟩ : āˆ€ {Ī“ τ₁ τ₂}
    (e : var τ₁ (τ₁ ∷ Ī“) → exp-phoas var (τ₁ ∷ Ī“) τ₂)
    → exp-phoas var Ī“ (τ₁ āŸØā†’āŸ© τ₂)
  _āŸØāˆ™āŸ©_ : āˆ€ {Ī“ τ₁ τ₂}
    (e₁ : exp-phoas var Ī“ (τ₁ āŸØā†’āŸ© τ₂))
    (eā‚‚ : exp-phoas var Ī“ τ₁)
    → exp-phoas var Ī“ τ₂

infix 10 _∈_
data _∈_ {ā„“} {A : Set ā„“} (x : A) : āˆ€ (xs : ⟬ A ⟭) → Set ā„“ where
  Z : āˆ€ {xs} → x ∈ x ∷ xs
  S : āˆ€ {x′ xs} → x ∈ xs → x ∈ x′ ∷ xs

infix 10 _⊢_
data _⊢_ : āˆ€ (Ī“ : ⟬ type ⟭) (Ļ„ : type) → Set where
  Var : āˆ€ {Ī“ Ļ„}
    (x : Ļ„ ∈ Ī“)
    → Ī“ ⊢ Ļ„
  ⟨λ⟩ : āˆ€ {Ī“ τ₁ τ₂}
    (e : τ₁ ∷ Ī“ ⊢ τ₂)
    → Ī“ ⊢ τ₁ āŸØā†’āŸ© τ₂
  _āŸØāˆ™āŸ©_ : āˆ€ {Ī“ τ₁ τ₂}
    (e₁ : Ī“ ⊢ τ₁ āŸØā†’āŸ© τ₂)
    (eā‚‚ : Ī“ ⊢ τ₁)
    → Ī“ ⊢ τ₂

⟦_āŸ§ā‚ : āˆ€ {Ī“ Ļ„} (e : exp-phoas _∈_ Ī“ Ļ„) → Ī“ ⊢ Ļ„
⟦ Var x āŸ§ā‚ = Var x
⟦ ⟨λ⟩ e āŸ§ā‚ = ⟨λ⟩ ⟦ e Z āŸ§ā‚
⟦ e₁ āŸØāˆ™āŸ© eā‚‚ āŸ§ā‚ = ⟦ e₁ āŸ§ā‚ āŸØāˆ™āŸ© ⟦ eā‚‚ āŸ§ā‚

⟦_āŸ§ā‚‚ : āˆ€ {Ī“ Ļ„} (e : Ī“ ⊢ Ļ„) → exp-phoas _∈_ Ī“ Ļ„
⟦ Var x āŸ§ā‚‚ = Var x
⟦ ⟨λ⟩ e āŸ§ā‚‚ = ⟨λ⟩ (Ī» _ → ⟦ e āŸ§ā‚‚)
⟦ e₁ āŸØāˆ™āŸ© eā‚‚ āŸ§ā‚‚ = ⟦ e₁ āŸ§ā‚‚ āŸØāˆ™āŸ© ⟦ eā‚‚ āŸ§ā‚‚

Ch : type
Ch =  (āŸØā„•āŸ© āŸØā†’āŸ© āŸØā„•āŸ©) āŸØā†’āŸ© āŸØā„•āŸ© āŸØā†’āŸ© āŸØā„•āŸ©

twoDB : [] ⊢ Ch
twoDB = ⟨λ⟩ (⟨λ⟩ (Var (S Z) āŸØāˆ™āŸ© (Var (S Z) āŸØāˆ™āŸ© Var Z)))

twoPH : exp-phoas _∈_ [] Ch
twoPH = ⟨λ⟩ (Ī» f → ⟨λ⟩ (Ī» x → Var f āŸØāˆ™āŸ© (Var f āŸØāˆ™āŸ© Var x)))

{-
/Users/wadler/sf/src/extra/DaraisPhoas.agda:82,9-60
āŸØā„•āŸ© āŸØā†’āŸ© āŸØā„•āŸ© != āŸØā„•āŸ© of type type
when checking that the expression
⟨λ⟩ (Ī» f → ⟨λ⟩ (Ī» x → Var f āŸØāˆ™āŸ© (Var f āŸØāˆ™āŸ© Var x))) has type
exp-phoas _∈_ [] Ch
-}