【发布时间】:2018-01-20 23:24:55
【问题描述】:
这个问题是出于对 PL 如何工作的好奇,而不是其他任何事情。 (它实际上是在查看 SML 时想到的,它与 Haskell 的不同之处在于前者使用按值调用 - 但我的问题是关于 Haskell。)
Haskell(据我所知)具有“按需调用”语义。 这是否意味着如果我定义一个函数如下:
cond True thenExp elseExp = thenExp
cond _ thenExp elseExp = elseExp
这将始终与 if-then-else 表达式完全一样? 或者,在另一种意义上,是否可以将 if-then-else 视为可以定义为函数的东西的语法糖?
编辑:
为了对比 Haskell 与标准 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经常表现不同。 我的问题是这(按需要调用与按值调用)是否是这种差异背后的主要原因(并且共识似乎是“是”)。
【问题讨论】:
-
你的代码应该可以完美运行
-
我也会在这里使用
False,因为第一个表达式可能是undefined。 -
@WillemVanOnsem 我确实想知道除了
False之外的其他任何东西,虽然我不太熟悉它,但没有想到undefined -
@WillemVanOnsem 由于模式匹配,该函数在第一个参数中已经很严格。
True。所以使用_与False不会有什么不同。 -
另外请记住,在 Haskell 中,与在许多具有代数数据类型的 (FP) 语言中一样,
if条件不如case of(和其他相关的模式匹配结构)重要。通常,好的 Haskell 代码使用布尔值的频率要低得多。在 Haskell 中,我们永远不会有 Java 的Scanner.hasNext()和next(),后者在第一个返回 false 时抛出。我们只需要next :: .. -> Maybe Stuff(或一些单子变体),其中布尔值消失了,有利于更好的类型。