`if-then-else`(总是)可以用函数调用替换吗?

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通常表现不同.我的问题是这是否(按需调用与按价值调用)是这种差异背后的主要原因(并且共识似乎是"是").

Wil*_*sem 6

就像Haskell维基百科上if-then-else说:

对于处理条件,在Haskell98**中定义了`if-then-else`**语法.然而它可以简单地用函数"if"替换
if' :: Bool -> a -> a -> a
if' True  x _ = x
if' False _ y = y
Run Code Online (Sandbox Code Playgroud)

因此,如果我们使用上面的if'功能,我们需要评估它(因为Haskell是惰性的,我们没有必要需要评估的if- then- else表达的话),哈斯克尔将首先评估第一个操作数来决定,如果它是TrueFalse.如果是True,它将返回第一个表达式,如果是False,它将返回第二个表达式.请注意,这本身并不意味着我们(完全)评估这些表达式.只有当我们需要结果时,我们才会评估表达式.

但是在条件是这样的情况下True,根本没有理由评估第二个表达式,因为我们忽略它.

如果我们在表达式树的多个部分上共享一个表达式,那么另一个调用当然可以(部分地)计算另一个表达式.

ghci甚至有一个覆盖if <expr> then <expr> else <expr>语法的选项:-XRebindable标志.它除了其他东西之外还会:

条件(例如if e1 then e2 else e3)意味着ifThenElse e1 e2 e3.但是,案例表达不受影响.