--------------------------------------------------------------------------------
-- This is part of Agda Inference Systems 

open import Agda.Builtin.Equality
open import Data.Product
open import Level
open import Relation.Unary using (_βŠ†_)

module is-lib.InfSys.Induction {𝓁} where

  private
    variable
      U : Set 𝓁

  open import is-lib.InfSys.Base {𝓁}
  open MetaRule
  open IS

  {- Inductive Interpretation -}

  data Ind⟦_⟧ {𝓁c 𝓁p 𝓁n : Level} (is : IS {𝓁c} {𝓁p} {𝓁n} U) : U β†’  Set (𝓁 βŠ” 𝓁c βŠ” 𝓁p βŠ” 𝓁n) where
    fold : βˆ€{u} β†’ ISF[ is ] Ind⟦ is ⟧ u β†’ Ind⟦ is ⟧ u

  {- Induction Principle -}

  ind[_] : βˆ€{𝓁c 𝓁p 𝓁n 𝓁'} 
      β†’ (is : IS {𝓁c} {𝓁p} {𝓁n} U)  -- IS
      β†’ (S : U β†’ Set 𝓁')            -- specification
      β†’ ISClosed is S               -- S is closed
      β†’ Ind⟦ is ⟧ βŠ† S
  ind[ is ] S cl (fold (rn , c , refl , pr)) = cl rn c Ξ» i β†’ ind[ is ] S cl (pr i)

  {- Apply Rule -}
  
  apply-ind : βˆ€{𝓁c 𝓁p 𝓁n}{is : IS {𝓁c} {𝓁p} {𝓁n} U} β†’ (rn : is .Names) β†’ RClosed (is .rules rn) Ind⟦ is ⟧
  apply-ind {is = is} rn = prefixβ‡’closed (is .rules rn) {P = Ind⟦ _ ⟧} Ξ»{(c , refl , pr) β†’ fold (rn , c , refl , pr)}

  {- Postfix - Prefix -}

  ind-postfix : βˆ€{𝓁c 𝓁p 𝓁n}{is : IS {𝓁c} {𝓁p} {𝓁n} U} β†’ Ind⟦ is ⟧ βŠ† ISF[ is ] Ind⟦ is ⟧
  ind-postfix (fold x) = x

  ind-prefix : βˆ€{𝓁c 𝓁p 𝓁n}{is : IS {𝓁c} {𝓁p} {𝓁n} U} β†’ ISF[ is ] Ind⟦ is ⟧ βŠ† Ind⟦ is ⟧
  ind-prefix x = fold x