{-# OPTIONS --safe --sized-types #-}
module Generic.Examples.SystemF where
open import Size
open import Data.Unit
open import Data.Bool
open import Data.Product
open import Data.List.Base hiding ([_])
open import Function
open import Relation.Binary.PropositionalEquality hiding ([_])
open import Data.Var hiding (_<$>_)
open import Data.Var.Varlike
open import Data.Environment hiding (_<$>_)
open import Generic.Syntax
open import Generic.Semantics
open import Generic.Semantics.Syntactic
data Kind : Set where
Term Type : Kind
system-F : Desc Kind
system-F = `X [] Type (`X [] Type (`∎ Type))
`+ `X (Type ∷ []) Type (`∎ Type)
`+ `X [] Term (`X [] Term (`∎ Term))
`+ `X (Term ∷ []) Term (`∎ Term)
`+ `X [] Term (`X [] Type (`∎ Term))
`+ `X (Type ∷ []) Term (`∎ Term)
pattern arr a b = `con (true , a , b , refl)
pattern for b = `con (false , true , b , refl)
pattern app f t = `con (false , false , true , f , t , refl)
pattern lam b = `con (false , false , false , true , b , refl)
pattern App f t = `con (false , false , false , false , true , f , t , refl)
pattern Lam b = `con (false , false , false , false , false , b , refl)
SF : Kind → List Kind → Set
SF = Tm system-F ∞
data Redex {Γ : List Kind} : SF Term Γ → Set where
applam : (b : SF Term (Term ∷ Γ)) (u : SF Term Γ) → Redex (app (lam b) u)
AppLam : (b : SF Term (Type ∷ Γ)) (u : SF Type Γ) → Redex (App (Lam b) u)
[app-l] : {f : SF Term Γ} → Redex f → (t : SF Term Γ) → Redex (app f t)
[app-r] : (f : SF Term Γ) {t : SF Term Γ} → Redex t → Redex (app f t)
[lam] : {b : SF Term (Term ∷ Γ)} → Redex b → Redex (lam b)
[App] : {f : SF Term Γ} → Redex f → (t : SF Type Γ) → Redex (App f t)
[Lam] : {b : SF Term (Type ∷ Γ)} → Redex b → Redex (Lam b)
open import Category.Monad
open import Data.Maybe
open import Data.Maybe.Categorical
import Level
open RawMonadPlus (monadPlus {Level.zero})
redex : {Γ : List Kind} (t : SF Term Γ) → Maybe (Redex t)
redex (app (lam b) u) = just (applam b u)
redex (App (Lam b) u) = just (AppLam b u)
redex (app f t) = flip [app-l] t <$> redex f ∣ [app-r] f <$> redex t
redex (lam b) = [lam] <$> redex b
redex (App f t) = flip [App] t <$> redex f
redex (Lam b) = [Lam] <$> redex b
redex _ = nothing
fire : {Γ : List Kind} {t : SF Term Γ} → Redex t → SF Term Γ
fire (applam b u) = sub (base vl^Tm ∙ u) b
fire (AppLam b u) = sub (base vl^Tm ∙ u) b
fire ([app-l] f t) = app (fire f) t
fire ([app-r] f t) = app f (fire t)
fire ([lam] b) = lam (fire b)
fire ([App] f t) = App (fire f) t
fire ([Lam] b) = Lam (fire b)
open import Codata.Thunk
open import Codata.Colist
open import Codata.Colist.Bisimilarity using (_⊢_≈_; _∷_; [])
eval : ∀ {i} (Γ : List Kind) (t : SF Term Γ) → Colist (SF Term Γ) i
eval Γ t with redex t
... | just r = t ∷ λ where .force → eval Γ (fire r)
... | nothing = t ∷ λ where .force → []
`id : SF Term []
`id = Lam (lam (`var z))
_ : _ ⊢ eval [] (lam (lam (app (lam (app (`var z) (`var z))) (lam (`var z)))))
≈ fromList (_ ∷ _ ∷ lam (lam (lam (`var z))) ∷ [])
_ = refl ∷ λ where .force → refl ∷ λ where .force → refl ∷ λ where .force → []