嘿,我对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))
谢谢
答案 0 :(得分:4)
要理解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
我肯定在猜测Exp
类型的一些细节!
现在,这是怎么回事。这为基于lambda演算的非常简单的编程语言定义了抽象语法树。 Exp
的每个构造函数都是该语言的某种语法构造:函数应用程序(EApp
),lambda(EAbs
),if语句(EIf
),等等。 evalCBN
函数正在为该编程语言定义解释器或评估器。由于存在许多不同的语法构造,因此evalCBN
是通过 pattern matching 定义的,其中每种语法节点都有一个不同的等式,可能需要对其进行评估。因为树结构是递归的,所以评估函数也是递归的。
假设evalCBN
是指它使用“按需致电”策略而不是“按值致电”策略进行评估的事实。您可以在应用函数的方程式中看到这一点:
evalCBN (EApp e1 e2) = case (evalCBN e1) of
(EAbs i e1') -> evalCBN (subst i e2 e1')
e1' -> EApp e1' e2
请注意,根本不评估参数e2
。相反,它只是以其未赋值的形式替换为表达式e1'
。按值变化的调用会在替换e2
之前对其进行评估。
ELet
和ERec
(非递归让和递归让)的方程式很有趣,因为它们所做的只是将ELet
或ERec
重写为不同的表达式,然后求值。这是所谓的“语法糖”的一个很好的例子。这些句法形式并不能使语言更具表达力。取而代之的是,它们在“回避”过程中被浅化为基本形式。
如果您还有其他问题,请提出更具体的问题。这些代码很多,所以我无法回答所有问题!