扩展无类型 Lambda 演算实现以涵盖简单类型 Lambda 演算需要什么?
What is required to extend an Untyped Lambda calculus implementation to cover the Simply Typed Lambda Calculus?
Matt Might talks about implementing a Lambda Calculus interpreter in 7 lines of Scheme:
; eval takes an expression and an environment to a value
(define (eval e env) (cond
((symbol? e) (cadr (assq e env)))
((eq? (car e) 'λ) (cons e env))
(else (apply (eval (car e) env) (eval (cadr e) env)))))
; apply takes a function and an argument to a value
(define (apply f x)
(eval (cddr (car f)) (cons (list (cadr (car f)) x) (cdr f))))
; read and parse stdin, then evaluate:
(display (eval (read) '())) (newline)
现在这不是 Simply Typed Lambda Calculus. In the core of Haskell, there is an Intermediate Language that bears a strong resemblance to System F. Some (including Simon Peyton Jones) have called this an implementation of the Simply Typed Lambda Calculus。
我的问题是:扩展无类型 Lambda 演算实现以涵盖简单类型 Lambda 演算需要什么?
不太清楚你在问什么,但我可以想到几个有效的答案:
需要更改表示以适应 lambda 抽象引入的变量的类型注释。
根据您的表示,可能会表示类型不正确的术语。如果是这样,您将需要实施类型检查器。
对于评估,您无需更改 LC 评估程序中的任何内容,只需忽略类型注释(这就是 type erasure 的重点)。但是,如果您编写的求值器基本上是 evalUntyped . eraseTypes
,那么与编写定制的 evalTyped
函数相比,您可能更难证明它是完整的。
简单类型的 lambda 演算 (STLC) 只是向您描述的系统添加类型检查器。也就是说,您可以将此评估器视为 STLC 的 "run-time system"。
侧节点:通常将类型注释添加到语言中以简化类型检查器的工作,但这不是必需的。
上面有一些很好的答案 - 我无意贬低他们。
在实现类型检查器方面 - 在 Haskell 中更简单(尽管可以想象这可以移植到 Scheme)。
这是 Haskell that is an implementation of the Simply Typed Lambda Calculus:
中的简单类型检查器
type OType = ObjType (Fix ObjType)
type OEnvironment = Map TermIdentifier OType
check :: OEnvironment -> Term OType -> OType
check env (Var i) = case lookup i env of
Nothing -> error $ "Unbound variable " ++ i
Just v -> v
check env (App f p) = let t_f = check env f
t_p = check env p
in case t_f of
Fun (Fix t_p') (Fix r)
| t_p == t_p' -> r
| otherwise -> error "Parameter mismatch"
_ -> error "Applied a non-function"
check env (Lam i ty t) = let r = check (insert i ty env) t
in Fun (Fix ty) (Fix r)
这是 Haskell 中简单类型 Lambda 演算的 :
import Control.Applicative ((<$), (<$>))
import Control.Monad (guard)
import Safe (atMay)
data Type
= Base
| Arrow Type Type
deriving (Eq, Ord, Read, Show)
data Term
= Const
| Var Int -- deBruijn indexing; the nearest enclosing lambda binds Var 0
| Lam Type Term
| App Term Term
deriving (Eq, Ord, Read, Show)
check :: [Type] -> Term -> Maybe Type
check env Const = return Base
check env (Var v) = atMay env v
check env (Lam ty tm) = Arrow ty <$> check (ty:env) tm
check env (App tm tm') = do
Arrow i o <- check env tm
i' <- check env tm'
guard (i == i')
return o
eval :: Term -> Term
eval (App tm tm') = case eval tm of
Lam _ body -> eval (subst 0 tm' body)
eval v = v
subst :: Int -> Term -> Term -> Term
subst n tm Const = Const
subst n tm (Var m) = case compare m n of
LT -> Var m
EQ -> tm
GT -> Var (m-1)
subst n tm (Lam ty body) = Lam ty (subst (n+1) tm body)
subst n tm (App tm' tm'') = App (subst n tm tm') (subst n tm tm'')
evalMay :: Term -> Maybe Term
evalMay tm = eval tm <$ check [] tm
Matt Might talks about implementing a Lambda Calculus interpreter in 7 lines of Scheme:
; eval takes an expression and an environment to a value
(define (eval e env) (cond
((symbol? e) (cadr (assq e env)))
((eq? (car e) 'λ) (cons e env))
(else (apply (eval (car e) env) (eval (cadr e) env)))))
; apply takes a function and an argument to a value
(define (apply f x)
(eval (cddr (car f)) (cons (list (cadr (car f)) x) (cdr f))))
; read and parse stdin, then evaluate:
(display (eval (read) '())) (newline)
现在这不是 Simply Typed Lambda Calculus. In the core of Haskell, there is an Intermediate Language that bears a strong resemblance to System F. Some (including Simon Peyton Jones) have called this an implementation of the Simply Typed Lambda Calculus。
我的问题是:扩展无类型 Lambda 演算实现以涵盖简单类型 Lambda 演算需要什么?
不太清楚你在问什么,但我可以想到几个有效的答案:
需要更改表示以适应 lambda 抽象引入的变量的类型注释。
根据您的表示,可能会表示类型不正确的术语。如果是这样,您将需要实施类型检查器。
对于评估,您无需更改 LC 评估程序中的任何内容,只需忽略类型注释(这就是 type erasure 的重点)。但是,如果您编写的求值器基本上是
evalUntyped . eraseTypes
,那么与编写定制的evalTyped
函数相比,您可能更难证明它是完整的。
简单类型的 lambda 演算 (STLC) 只是向您描述的系统添加类型检查器。也就是说,您可以将此评估器视为 STLC 的 "run-time system"。
侧节点:通常将类型注释添加到语言中以简化类型检查器的工作,但这不是必需的。
上面有一些很好的答案 - 我无意贬低他们。
在实现类型检查器方面 - 在 Haskell 中更简单(尽管可以想象这可以移植到 Scheme)。
这是 Haskell that is an implementation of the Simply Typed Lambda Calculus:
中的简单类型检查器type OType = ObjType (Fix ObjType)
type OEnvironment = Map TermIdentifier OType
check :: OEnvironment -> Term OType -> OType
check env (Var i) = case lookup i env of
Nothing -> error $ "Unbound variable " ++ i
Just v -> v
check env (App f p) = let t_f = check env f
t_p = check env p
in case t_f of
Fun (Fix t_p') (Fix r)
| t_p == t_p' -> r
| otherwise -> error "Parameter mismatch"
_ -> error "Applied a non-function"
check env (Lam i ty t) = let r = check (insert i ty env) t
in Fun (Fix ty) (Fix r)
这是 Haskell 中简单类型 Lambda 演算的
import Control.Applicative ((<$), (<$>))
import Control.Monad (guard)
import Safe (atMay)
data Type
= Base
| Arrow Type Type
deriving (Eq, Ord, Read, Show)
data Term
= Const
| Var Int -- deBruijn indexing; the nearest enclosing lambda binds Var 0
| Lam Type Term
| App Term Term
deriving (Eq, Ord, Read, Show)
check :: [Type] -> Term -> Maybe Type
check env Const = return Base
check env (Var v) = atMay env v
check env (Lam ty tm) = Arrow ty <$> check (ty:env) tm
check env (App tm tm') = do
Arrow i o <- check env tm
i' <- check env tm'
guard (i == i')
return o
eval :: Term -> Term
eval (App tm tm') = case eval tm of
Lam _ body -> eval (subst 0 tm' body)
eval v = v
subst :: Int -> Term -> Term -> Term
subst n tm Const = Const
subst n tm (Var m) = case compare m n of
LT -> Var m
EQ -> tm
GT -> Var (m-1)
subst n tm (Lam ty body) = Lam ty (subst (n+1) tm body)
subst n tm (App tm' tm'') = App (subst n tm tm') (subst n tm tm'')
evalMay :: Term -> Maybe Term
evalMay tm = eval tm <$ check [] tm