perga/lib/Eval.hs

114 lines
3.6 KiB
Haskell
Raw Normal View History

2024-11-22 19:44:31 -08:00
{-# LANGUAGE NamedFieldPuns #-}
2024-11-17 18:33:14 -08:00
2024-11-17 01:57:53 -08:00
module Eval where
2024-11-22 19:44:31 -08:00
import Control.Monad.Error.Class
import qualified Data.Map.Strict as M
2024-11-17 18:33:14 -08:00
import Errors
2024-11-17 01:57:53 -08:00
import Expr
2024-11-22 19:44:31 -08:00
import Relude.Extra.Lens
2024-11-17 01:57:53 -08:00
2024-11-22 19:44:31 -08:00
data Definition = Def {_ty :: Expr, _val :: Expr}
makeDef :: Expr -> Expr -> Definition
makeDef typ value = Def{_ty = typ, _val = value}
tyL :: Lens' Definition Expr
tyL = lens _ty setter
where
setter (Def{_val}) new = Def{_val, _ty = new}
valL :: Lens' Definition Expr
valL = lens _val setter
where
setter (Def{_ty}) new = Def{_val = new, _ty}
type Env = Map Text Definition
2024-11-17 01:57:53 -08:00
emptyEnv :: Env
emptyEnv = M.empty
2024-11-22 19:44:31 -08:00
showEnvEntry :: Text -> Definition -> Text
showEnvEntry k Def{_ty = t} = k <> " : " <> pretty t
dumpEnv :: Env -> IO ()
2024-11-22 19:44:31 -08:00
dumpEnv = void . M.traverseWithKey ((putTextLn .) . showEnvEntry)
2024-11-17 01:57:53 -08:00
-- substitute s for k *AND* decrement indices; only use after reducing a redex.
subst :: Integer -> Expr -> Expr -> Expr
2024-11-22 19:44:31 -08:00
subst k s (Var x n)
2024-11-17 01:57:53 -08:00
| k == n = s
2024-11-22 19:44:31 -08:00
| n > k = Var x (n - 1)
| otherwise = Var x n
2024-11-17 01:57:53 -08:00
subst _ _ (Free s) = Free s
2024-11-20 07:37:49 -08:00
subst _ _ (Axiom s) = Axiom s
2024-11-17 01:57:53 -08:00
subst _ _ Star = Star
subst _ _ Square = Square
subst k s (App m n) = App (subst k s m) (subst k s n)
subst k s (Abs x m n) = Abs x (subst k s m) (subst (k + 1) (incIndices s) n)
subst k s (Pi x m n) = Pi x (subst k s m) (subst (k + 1) (incIndices s) n)
2024-11-23 09:16:32 -08:00
subst k s (Let x v b) = Let x (subst k s v) (subst (k + 1) (incIndices s) b)
2024-11-17 01:57:53 -08:00
2024-11-20 07:37:49 -08:00
envLookupVal :: Text -> ReaderT Env Result Expr
envLookupVal n = asks ((_val <$>) . M.lookup n) >>= maybe (throwError $ UnboundVariable n) pure
envLookupTy :: Text -> ReaderT Env Result Expr
envLookupTy n = asks ((_ty <$>) . M.lookup n) >>= maybe (throwError $ UnboundVariable n) pure
2024-11-17 18:33:14 -08:00
2024-11-23 09:16:32 -08:00
-- reduce until β reducts or let simplifications are impossible in head position
2024-11-17 18:33:14 -08:00
whnf :: Expr -> ReaderT Env Result Expr
2024-11-17 01:57:53 -08:00
whnf (App (Abs _ _ v) n) = whnf $ subst 0 n v
2024-11-17 18:33:14 -08:00
whnf (App m n) = do
m' <- whnf m
if m == m'
then pure $ App m n
else whnf $ App m' n
whnf (Free n) = envLookupVal n >>= whnf
2024-11-23 09:16:32 -08:00
whnf (Let _ v b) = whnf $ subst 0 v b
2024-11-17 18:33:14 -08:00
whnf e = pure e
2024-11-17 01:57:53 -08:00
2024-11-18 14:33:21 -08:00
reduce :: Expr -> ReaderT Env Result Expr
reduce (App (Abs _ _ v) n) = pure $ subst 0 n v
reduce (App m n) = App <$> reduce m <*> reduce n
reduce (Abs x t v) = Abs x <$> reduce t <*> reduce v
reduce (Pi x t v) = Pi x <$> reduce t <*> reduce v
2024-11-20 07:37:49 -08:00
reduce (Free n) = envLookupVal n
2024-11-23 09:16:32 -08:00
reduce (Let _ v b) = pure $ subst 0 v b
2024-11-18 14:33:21 -08:00
reduce e = pure e
normalize :: Expr -> ReaderT Env Result Expr
normalize e = do
e' <- reduce e
if e == e'
then pure e
else normalize e'
2024-11-17 18:33:14 -08:00
betaEquiv :: Expr -> Expr -> ReaderT Env Result Bool
betaEquiv e1 e2
| e1 == e2 = pure True
| otherwise = do
e1' <- whnf e1
e2' <- whnf e2
case (e1', e2') of
(Var k1 _, Var k2 _) -> pure $ k1 == k2
(Free n, Free m) -> pure $ n == m
(Axiom n, Axiom m) -> pure $ n == m
(Free n, e) -> envLookupVal n >>= betaEquiv e
(e, Free n) -> envLookupVal n >>= betaEquiv e
(Star, Star) -> pure True
(Abs _ t1 v1, Abs _ t2 v2) -> (&&) <$> betaEquiv t1 t2 <*> betaEquiv v1 v2 -- i want idiom brackets
(Pi _ t1 v1, Pi _ t2 v2) -> (&&) <$> betaEquiv t1 t2 <*> betaEquiv v1 v2
(App m1 n1, App m2 n2) -> (&&) <$> betaEquiv m1 m2 <*> betaEquiv n1 n2
_ -> pure False -- remaining cases impossible or false
2024-11-17 18:33:14 -08:00
checkBeta :: Env -> Expr -> Expr -> Result Bool
checkBeta env e1 e2 = runReaderT (betaEquiv e1 e2) env
isSortPure :: Expr -> Bool
isSortPure Star = True
isSortPure Square = True
isSortPure _ = False
2024-11-22 19:44:31 -08:00
isSort :: Expr -> ReaderT Env Result Bool
isSort = fmap isSortPure . whnf