perga/lib/Check.hs

95 lines
2.9 KiB
Haskell
Raw Normal View History

2024-11-17 18:33:14 -08:00
{-# LANGUAGE LambdaCase #-}
2024-11-22 19:44:31 -08:00
module Check (checkType, findType) where
2024-10-05 13:31:09 -07:00
import Control.Monad.Except (MonadError (throwError), liftEither)
2024-11-17 01:57:53 -08:00
import Data.List ((!?))
2024-11-17 18:33:14 -08:00
import Errors
import Eval (Env, betaEquiv', envLookupTy, subst, whnf)
2024-11-17 18:33:14 -08:00
import Expr (Expr (..), incIndices, occursFree)
2024-10-05 13:31:09 -07:00
type Context = [Expr]
2024-11-17 18:33:14 -08:00
matchPi :: Expr -> Expr -> ReaderT Env Result (Expr, Expr)
matchPi x mt =
whnf mt >>= \case
(Pi _ a b) -> pure (a, b)
2024-11-17 18:33:14 -08:00
t -> throwError $ ExpectedPiType x t
2024-11-11 17:57:14 -08:00
2025-01-25 10:39:50 -08:00
matchProd :: Expr -> Expr -> ReaderT Env Result (Expr, Expr)
matchProd x mt =
whnf mt >>= \case
(Prod a b) -> pure (a, b)
t -> throwError $ ExpectedProdType x t
findLevel :: Context -> Expr -> ReaderT Env Result Integer
findLevel g a = do
2024-11-22 19:44:31 -08:00
s <- findType g a
whnf s >>= \case
Level i -> pure i
Star -> pure $ -1 -- HACK: but works, so...
2024-12-08 12:40:52 -08:00
_ -> throwError $ NotASort a
2024-11-22 19:44:31 -08:00
validateType :: Context -> Expr -> ReaderT Env Result ()
validateType g a = void $ findLevel g a
2024-11-22 19:44:31 -08:00
isSort :: Expr -> Bool
isSort Star = True
isSort (Level _) = True
isSort _ = False
compSort :: Expr -> Expr -> Expr -> Expr -> Result Expr
compSort _ _ Star Star = pure Star
compSort _ _ Star r@(Level _) = pure r
compSort _ _ (Level i) Star
| i == 0 = pure Star
| otherwise = pure $ Level i
compSort _ _ (Level i) (Level j) = pure $ Level $ max i j
2024-12-08 12:40:52 -08:00
compSort a b left _
| isSort left = throwError $ NotASort b
| otherwise = throwError $ NotASort a
2024-11-17 18:33:14 -08:00
findType :: Context -> Expr -> ReaderT Env Result Expr
findType _ Star = pure $ Level 0
findType _ (Level i) = pure $ Level (i + 1)
2024-11-22 19:44:31 -08:00
findType g (Var x n) = do
t <- g !? fromInteger n `whenNothing` throwError (UnboundVariable x)
validateType g t
2024-11-11 13:37:44 -08:00
pure t
findType _ (Free n) = envLookupTy n
findType _ (Axiom n) = envLookupTy n
2024-11-12 00:00:51 -08:00
findType g e@(App m n) = do
(a, b) <- findType g m >>= matchPi m
2024-11-11 13:37:44 -08:00
a' <- findType g n
betaEquiv' e a a'
pure $ subst 0 n b
findType g (Abs x a m) = do
validateType g a
2024-11-11 17:57:14 -08:00
b <- findType (incIndices a : map incIndices g) m
validateType g (Pi x a b)
pure $ if occursFree 0 b then Pi x a b else Pi "" a b
findType g (Pi _ a b) = do
aSort <- findType g a
bSort <- findType (incIndices a : map incIndices g) b
liftEither $ compSort a b aSort bSort
2024-11-30 22:36:27 -08:00
findType g (Let _ Nothing v b) = findType g (subst 0 v b)
findType g e@(Let _ (Just t) v b) = do
res <- findType g (subst 0 v b)
2024-12-05 19:05:34 -08:00
_ <- findType g t
betaEquiv' e t res
2024-11-30 22:36:27 -08:00
pure t
2025-01-25 10:39:50 -08:00
findType g (Prod a b) = do
aSort <- findType g a
bSort <- findType g b
liftEither $ compSort a b aSort bSort
findType g (Pair a b) = do
aType <- findType g a
bType <- findType g b
validateType g $ Prod aType bType
pure $ Prod aType bType
findType g (Pi1 x) = fst <$> (findType g x >>= matchProd x)
findType g (Pi2 x) = snd <$> (findType g x >>= matchProd x)
2024-11-17 01:57:53 -08:00
2024-11-17 18:33:14 -08:00
checkType :: Env -> Expr -> Result Expr
checkType env t = runReaderT (findType [] t) env