(图1)
简单类型的lambda演算的一部分(图1),它在Haskell中实现,如下所示。
evaluate expression = do
case expression of
(Application (Lambda x ltype term) value) | isValue value = True -> substitute term x value
(Application value e2) | isValue value = True -> let e22 = evaluate e2 in Application value e22
(Application e1 e2) -> let e11 = evaluate e1 in Application e11 e2
但是,这不适用于这些测试用例,
1)print (evaluate (Application (Var "x") (Var "y")))
2)print (evaluate (Application (Constant 3) (Var "y"))
“(常数3)是一个值”
但是,对于第一个测试用例,我知道这是因为(Var "x")
为e1
是终端,因此无法转换。这是否意味着我应该添加Stuck
案例?但是如果可能的话,我想返回一个表明转换成功的输出。
提前谢谢你......
答案 0 :(得分:4)
如果您正在将lambda演算AST实现为
data Exp = Var String
| Constant Int
| App Exp Exp
| Lam String Exp
然后解释器evaluate :: Exp -> Out
可以产生许多值,有些是输入不良的结果。例如
evaluate (Lam "f" (Lam "x" (App (Var "f") (Var "x")))
-- type like (a -> b) -> a -> b
evaluate (Var "x")
-- open term, evaluation gets stuck
evaluate (App (Lam "x" (Constant 4)) (Constant 3))
-- term results in a constant
我们需要在返回类型中表示所有这些类型。一种典型的方法是使用类似
的通用类型data Out
= Stuck
| I Int
| F (Out -> Out)
再次强调需要卡住的情况。如果我们检查App
evaluate
分支
evaluate (App e1 e2) = case evaluate e1 of
Stuck -> Stuck
I i -> Stuck
F f -> f (evaluate e2)
显示Stuck
个案件如何上升到顶部,并且可能来自输入不良的字词。
在Haskell中有很多方法可以编写类型很好的简单类型的lambda演算类型。我非常喜欢Higher-Order Abstract Syntax Final Encoding。它非常对称。
class STLC rep where
lam :: (rep a -> rep b) -> rep (a -> b)
app :: rep (a -> b) -> (rep a -> rep b)
int :: Int -> rep Int
newtype Interpreter a = Reify { interpret :: a } -- just the identity monad
instance STLC Interpreter where
lam f = Reify $ interpret . f . Reify
app f a = Reify $ interpret f $ interpret a
int = Reify
在这个公式中,根本不可能编写一种类型STLC rep => rep a
,它不是很好的类型,也不会粘在上面。 interpret
的类型也表明了这一点
interpret :: Interpreter a -> a
否Out
- 即刻输入。
答案 1 :(得分:0)
但是,substitute
如何工作(即haskell中substitute
函数的实现是什么)。