Bil*_*ill 0 haskell programming-languages
嘿,我对 haskell 很陌生,我似乎不太明白这段代码中发生了什么
execCBN :: Program -> Exp
execCBN (Prog e) = evalCBN e
evalCBN :: Exp -> Exp
evalCBN (EApp e1 e2) = case (evalCBN e1) of
(EAbs i e1') -> evalCBN (subst i e2 e1')
e1' -> EApp e1' e2
evalCBN (EIf e1 e2 e3 e4) = if (evalCBN e1) == (evalCBN e2) then evalCBN e3 else evalCBN e4
evalCBN (ELet i e1 e2) = evalCBN (EApp (EAbs i e2) e1)
evalCBN (ERec i e1 e2) = evalCBN (EApp (EAbs i e2) (EFix (EAbs i e1))
Run Code Online (Sandbox Code Playgroud)
谢谢
要理解 Haskell 代码,您通常需要首先查看类型!您没有将它们包含在这里,但它们可能看起来像这样:
newtype Program = Program Exp
data Exp
= EApp Exp Exp
| EAbs String Exp
| EIf Exp Exp Exp Exp
| ELet String Exp Exp
| ERec String Exp Exp
| EFix Exp
| EVar String
Run Code Online (Sandbox Code Playgroud)
Exp我肯定会猜测该类型的一些细节!
现在,事情是这样的。这为基于 lambda 演算的非常简单的编程语言定义了抽象语法树。for 的每个构造函数Exp都是该语言中的某种语法构造:函数应用程序 ( EApp)、lambda ( EAbs)、if 语句 ( EIf) 等等。该evalCBN函数正在为该编程语言定义一个解释器或评估器。因为有许多不同的语法结构,所以evalCBN是用模式匹配定义的,其中可能需要评估的每种语法节点都有不同的方程。因为树结构是递归的,所以评价函数也是递归的。
据推测,该名称evalCBN指的是它正在使用“按需求调用”策略进行评估,而不是“按值调用”策略。您可以在应用函数的方程中看到:
evalCBN (EApp e1 e2) = case (evalCBN e1) of
(EAbs i e1') -> evalCBN (subst i e2 e1')
e1' -> EApp e1' e2
Run Code Online (Sandbox Code Playgroud)
请注意该参数e2是如何根本不被求值的。相反,它只是以其未计算的形式替换到表达式中e1'。按值变化的调用将e2在替换之前进行评估。
ELetand的方程ERec(非递归 let 和递归 let)很有趣,因为它们所做的只是将ELetor重写ERec为不同的表达式,然后对其求值。这是所谓的“语法糖”的一个很好的例子。这些句法形式并没有使语言更具表现力;而是使语言变得更具表现力。相反,它们在“脱糖”过程中被浅层重写为更基本的形式。
如果您还有其他问题,请提出更具体的问题。这段代码涉及很多内容,所以我无法全部回答!