packages feed

lambda-cube-0.3.0.0: src/LambdaCube/SystemFw/TypeChecker.hs

module LambdaCube.SystemFw.TypeChecker
  ( reduceType

  , infer
  , inferKind
  ) where

import           Data.List                        (uncons)
import           LambdaCube.SystemFw.Ast
import           LambdaCube.SystemFw.Substitution

reduceType :: LCType -> LCType
reduceType = go
  where
    go LCBase = LCBase
    go e@(LCTVar _) = e
    go (LCArr a b) = go a `LCArr` go b
    go (LCUniv k a) = LCUniv k $ go a
    go (LCTTLam k b) = LCTTLam k $ go b
    go (LCTTApp f a)
      | LCTTLam _ b <- go f
      , v <- go a
      = go $ substituteTypeInType v 0 b
      | otherwise
      = error "Did you really kind check this?"

infer :: LCTerm -> LCType
infer = go [] []
  where
    go _  tl (LCVar n) = maybe (error "Out-of-scope variable") fst . uncons $ drop n tl
    go kl tl (LCLam t b)
      | LCStar <- inferKind kl t
      = v `LCArr` go kl (v : tl) b
      | otherwise
      = error "Function argument kind mismatch"
      where
        v = reduceType t
    go kl tl (LCApp f a)
      | LCArr at rt <- go kl tl f
      , at == go kl tl a
      = rt
      | otherwise
      = error "Function argument type mismatch"
    go kl tl (LCTLam k b) = LCUniv k $ go (k : kl) (fmap (shiftType . (, 1)) tl) b
    go kl tl (LCTApp f t)
      | LCUniv tk rt <- go kl tl f
      , tk == inferKind kl t
      = substituteTypeInType v 0 rt
      | otherwise
      = error "Function argument kind mismatch"
      where
        v = reduceType t

inferKind :: [LCKind] -> LCType -> LCKind
inferKind = go
  where
    go _  LCBase = LCStar
    go kl (LCTVar n) = maybe (error "Out-of-scope variable") fst . uncons $ drop n kl
    go kl (LCArr a b)
      | LCStar <- go kl a
      , LCStar <- go kl b
      = LCStar
      | otherwise
      = error "Arrow kind mismatch"
    go kl (LCUniv k a) = go (k : kl) a
    go kl (LCTTLam k b) = LCKArr k $ go (k : kl) b
    go kl (LCTTApp f a)
      | LCKArr ak rk <- go kl f
      , ak == go kl a
      = rk
      | otherwise
      = error "Function argument kind mismatch"