Aky*_*Aky 2 haskell lazy-evaluation
这个问题是关于PL如何工作的好奇心,而不是其他任何问题.(实际上,我看到的是SML,它与Haskell的不同之处在于前者使用call-by-value - 但我的问题是关于Haskell.)
Haskell(据我所知)有"按需调用"语义.这是否意味着如果我定义一个函数如下:
cond True thenExp elseExp = thenExp
cond _ thenExp elseExp = elseExp
Run Code Online (Sandbox Code Playgroud)
这将总是表现得像if-then-else表达式?或者,在另一种意义上,if-then-else可以被视为可以被定义为函数的东西的语法糖?
编辑:
只是为了对比Haskell与Standard ML的行为,定义(在SML中)
cond p t f = if p then t else f;
然后是阶乘函数
fun factc n = cond (n=0) 1 (n * factc (n-1));
评估factc 1(说)永远不会完成,因为最后一个参数中的递归cond永远不会终止.
但是,定义
fun fact n = if n=0 then 1 else fact (n-1);
按预期工作,因为then分支仅根据需要进行评估.
也许有一些聪明的方法可以推迟SML中的参数评估(不知道我还不熟悉它)但重点是,在一个按值调用的类型语言中,if-then-else通常表现不同.我的问题是这是否(按需调用与按价值调用)是这种差异背后的主要原因(并且共识似乎是"是").
对于处理条件,在Haskell98**中定义了`if-then-else`**语法.然而它可以简单地用函数"if"替换Run Code Online (Sandbox Code Playgroud)if' :: Bool -> a -> a -> a if' True x _ = x if' False _ y = y
因此,如果我们使用上面的if'功能,我们需要评估它(因为Haskell是惰性的,我们没有必要需要评估的if- then- else表达的话),哈斯克尔将首先评估第一个操作数来决定,如果它是True或False.如果是True,它将返回第一个表达式,如果是False,它将返回第二个表达式.请注意,这本身并不意味着我们(完全)评估这些表达式.只有当我们需要结果时,我们才会评估表达式.
但是在条件是这样的情况下True,根本没有理由评估第二个表达式,因为我们忽略它.
如果我们在表达式树的多个部分上共享一个表达式,那么另一个调用当然可以(部分地)计算另一个表达式.
ghci甚至有一个覆盖if <expr> then <expr> else <expr>语法的选项:-XRebindable标志.它除了其他东西之外还会:
条件(例如
if e1 then e2 else e3)意味着ifThenElse e1 e2 e3.但是,案例表达不受影响.