module linear.Typing.Functional where open import Data.Nat open import Data.Product open import Function open import Relation.Binary.PropositionalEquality open import linear.Type open import linear.Context open import linear.Language open import linear.Usage open import linear.Usage.Functional open import linear.Typing open import linear.Relation.Functional RPattern : (i : Type × Σ[ m ∈ ℕ ] Pattern m) (o : let (_ , m , _) = i in Context m) → Set RPattern (A , _ , p) δ = A ∋ p ↝ δ functionalPattern : Functional′ RPattern functionalPattern _ `v `v = refl functionalPattern _ `⟨⟩ `⟨⟩ = refl functionalPattern _ (p₁ ,, q₁) (p₂ ,, q₂) = cong₂ _ (functionalPattern _ p₁ p₂) (functionalPattern _ q₁ q₂) functionalInfer : Functional (InferTyping TInfer) functionalInfer _ (`var k₁) (`var k₂) = functionalFin _ k₁ k₂ functionalInfer _ (`app t₁ u₁) (`app t₂ u₂) = cong (λ { (_ ─o τ) → τ; σ → σ }) $ functionalInfer _ t₁ t₂ functionalInfer _ (`fst t₁) (`fst t₂) = cong (λ { (σ & _) → σ; σ → σ}) $ functionalInfer _ t₁ t₂ functionalInfer _ (`snd t₁) (`snd t₂) = cong (λ { (_ & τ) → τ; σ → σ}) $ functionalInfer _ t₁ t₂ functionalInfer _ (`case t₁ return σ₁ of l₁ %% r₁) (`case t₂ return .σ₁ of l₂ %% r₂) = refl functionalInfer _ (`exfalso σ₁ t₁) (`exfalso σ₂ t₂) = refl functionalInfer _ (`cut t₁) (`cut t₂) = refl mutual functionalInferPost : Functional′ (InferTypingPost TInfer) functionalInferPost _ (`var x₁) (`var x₂) = functionalFinPost _ x₁ x₂ functionalInferPost _ (`app t₁ u₁) (`app t₂ u₂) with functionalInferPost _ t₁ t₂ ... | refl = cong _ $ functionalCheckPost _ u₁ u₂ functionalInferPost _ (`fst t₁) (`fst t₂) with functionalInferPost _ t₁ t₂ ... | refl = refl functionalInferPost _ (`snd t₁) (`snd t₂) with functionalInferPost _ t₁ t₂ ... | refl = refl functionalInferPost _ (`case t₁ return σ₁ of l₁ %% r₁) (`case t₂ return .σ₁ of l₂ %% r₂) with functionalInferPost _ t₁ t₂ ... | refl with functionalCheckPost _ l₁ l₂ ... | refl = refl functionalInferPost _ (`exfalso σ₁ t₁) (`exfalso σ₂ t₂) with functionalInferPost _ t₁ t₂ ... | refl = refl functionalInferPost _ (`cut t₁) (`cut t₂) = cong _ $ functionalCheckPost _ t₁ t₂ functionalCheckPost : Functional′ (CheckTypingPost TCheck) functionalCheckPost _ (`lam t₁) (`lam t₂) with functionalCheckPost _ t₁ t₂ ... | refl = refl functionalCheckPost (n , γ , Γ , σ , `let p ∷= t `in u) (`let_∷=_`in_ {δ = δ} p₁ t₁ u₁) (`let p₂ ∷= t₂ `in u₂) with functionalInferPost _ t₁ t₂ ... | refl with functionalPattern _ p₁ p₂ ... | refl = functional++ ]] δ [[ refl (functionalCheckPost _ u₁ u₂) functionalCheckPost _ `unit `unit = refl functionalCheckPost _ (`prd⊗ a₁ b₁) (`prd⊗ a₂ b₂) with functionalCheckPost _ a₁ a₂ ... | refl = functionalCheckPost _ b₁ b₂ functionalCheckPost _ (`prd& a₁ b₁) (`prd& a₂ b₂) = functionalCheckPost _ a₁ a₂ functionalCheckPost _ (`inl t₁) (`inl t₂) = functionalCheckPost _ t₁ t₂ functionalCheckPost _ (`inr t₁) (`inr t₂) = functionalCheckPost _ t₁ t₂ functionalCheckPost _ (`neu t₁) (`neu t₂) = cong proj₂ $ functionalInferPost _ t₁ t₂ mutual functionalInferPre : Functional′ (InferTypingPre TInfer) functionalInferPre _ (`var k₁) (`var k₂) = functionalFinPre _ k₁ k₂ functionalInferPre _ (`app t₁ u₁) (`app t₂ u₂) with functionalInfer _ t₁ t₂ ... | refl with functionalCheckPre _ u₁ u₂ ... | refl with functionalInferPre _ t₁ t₂ ... | refl = refl functionalInferPre _ (`fst t₁) (`fst t₂) with functionalInfer _ t₁ t₂ ... | refl with functionalInferPre _ t₁ t₂ ... | refl = refl functionalInferPre _ (`snd t₁) (`snd t₂) with functionalInfer _ t₁ t₂ ... | refl with functionalInferPre _ t₁ t₂ ... | refl = refl functionalInferPre _ (`case t₁ return σ of l₁ %% r₁) (`case t₂ return .σ of l₂ %% r₂) with functionalInfer _ t₁ t₂ ... | refl with functionalCheckPre _ r₁ r₂ ... | refl with functionalInferPre _ t₁ t₂ ... | refl = refl functionalInferPre _ (`exfalso σ₁ t₁) (`exfalso σ₂ t₂) with functionalInferPre _ t₁ t₂ ... | refl = refl functionalInferPre _ (`cut t₁) (`cut t₂) = cong _ $ functionalCheckPre _ t₁ t₂ functionalCheckPre : Functional′ (CheckTypingPre TCheck) functionalCheckPre _ (`lam t₁) (`lam t₂) with functionalCheckPre _ t₁ t₂ ... | refl = refl functionalCheckPre _ (`let p₁ ∷= t₁ `in u₁) (`let p₂ ∷= t₂ `in u₂) with functionalInfer _ t₁ t₂ ... | refl with functionalPattern _ p₁ p₂ ... | refl with functional++ [[ patternContext p₁ ]] refl (functionalCheckPre _ u₁ u₂) ... | refl = cong proj₂ $ functionalInferPre _ t₁ t₂ functionalCheckPre _ `unit `unit = refl functionalCheckPre _ (`prd⊗ a₁ b₁) (`prd⊗ a₂ b₂) rewrite functionalCheckPre _ b₁ b₂ = functionalCheckPre _ a₁ a₂ functionalCheckPre _ (`prd& a₁ b₁) (`prd& a₂ b₂) = functionalCheckPre _ a₁ a₂ functionalCheckPre _ (`inl t₁) (`inl t₂) = functionalCheckPre _ t₁ t₂ functionalCheckPre _ (`inr t₁) (`inr t₂) = functionalCheckPre _ t₁ t₂ functionalCheckPre _ (`neu t₁) (`neu t₂) = cong proj₂ $ functionalInferPre _ t₁ t₂