diff options
| author | Arnaud Bailly <arnaud@pankzsoft.com> | 2025-11-06 07:51:11 +0100 |
|---|---|---|
| committer | Arnaud Bailly <arnaud@pankzsoft.com> | 2025-11-06 07:51:11 +0100 |
| commit | 15c684d437da53ddfb88bbc9ad566588f89732c1 (patch) | |
| tree | 9cc325f7532f6117314d86131ef4d6705ad694ca /lambda-calcul/haskell/src/Minilang | |
| parent | ad0379c2b3813355264638b63c737cfaa8ee50dd (diff) | |
| download | lambda-nantes-15c684d437da53ddfb88bbc9ad566588f89732c1.tar.gz | |
draft env-based normaliser
Diffstat (limited to 'lambda-calcul/haskell/src/Minilang')
| -rw-r--r-- | lambda-calcul/haskell/src/Minilang/Lambda/Eval.hs | 48 |
1 files changed, 44 insertions, 4 deletions
diff --git a/lambda-calcul/haskell/src/Minilang/Lambda/Eval.hs b/lambda-calcul/haskell/src/Minilang/Lambda/Eval.hs index 7f7aad7..9d56c49 100644 --- a/lambda-calcul/haskell/src/Minilang/Lambda/Eval.hs +++ b/lambda-calcul/haskell/src/Minilang/Lambda/Eval.hs @@ -1,4 +1,5 @@ {-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE LambdaCase #-} module Minilang.Lambda.Eval where @@ -12,14 +13,53 @@ data Term | App Term Term deriving (Show, Read, Eq, Generic, ToJSON, FromJSON) +data Value = Clos EnvValue Text Term | VNeut Neutral + deriving (Show, Read, Eq) + +data Neutral = NVar Text | NApp Neutral Value + deriving (Show, Read, Eq) + type Env = [(Text, Term)] +type EnvValue = [(Text, Value)] + newEnv :: Env newEnv = [] -- call-by-value evaluator -eval :: Term -> Env -> Term -eval = undefined +-- from https://davidchristiansen.dk/tutorials/nbe/#%28part._untyped-eval%29 +eval :: EnvValue -> Term -> Value +eval env = \case + Var x -> case lookup x env of + Just term -> term + Nothing -> error $ "Unbound variable: " ++ show x + Lam x body -> Clos env x body + App f a -> apply (eval env f) (eval env a) + +apply :: Value -> Value -> Value +apply f a = + case f of + Clos closureEnv x body -> + let env' = (x, a) : closureEnv + in eval env' body + VNeut f' -> VNeut (NApp f' a) + +readBack :: Value -> Term +readBack = go [] + where + go names = \case + Clos env x body -> + let name = freshName x names + names' = name : names + val' = eval ((x, VNeut (NVar name)) : env) body + in Lam name (go names' val') + VNeut (NVar n) -> Var n + VNeut (NApp f a) -> App (go names (VNeut f)) (go names a) + +normalise :: Term -> Term +normalise term = readBack (eval [] term) -evalNeed :: Term -> Env -> Term -evalNeed = undefined +freshName :: Text -> [Text] -> Text +freshName x names + | x `elem` names = freshName (x <> "'") names + | otherwise = x |
