按名称调用vs在Haskell中按值调用

时间:2015-10-08 16:30:05

标签: haskell

如果按值调用并按名称调用有效,它们是否都会提供相同的结果? 例如:

import Debug.Trace 
trace :: String -> a -> a 
foo x y z = y + y + z
 z = foo (trace "first" 1) 
    (trace "second" 2)
    (trace "third" 3) 

 Call-By-Value: "first second third" 7
 Call-By-Name: "second second third" 7
  Lazy Evaluation: "second third" 7

在这种情况下,我们会得到三种不同的结果,但为什么呢?

1 个答案:

答案 0 :(得分:5)

不,你每次都得到相同的结果:7

其他消息(“first”等)是由于使用了调试函数Debug.Trace.trace,该函数用于生成一条消息,该消息准确地公开了表达式被评估。编程执行的“如何”部分通常不被认为是语义的一部分,即结果,而是只考虑返回“什么”。

例如,

的语义
let f x = x in f 10 + f 10

是20,与

相同
let f x = x in 2 * f 10

但是,如果我们添加痕迹,

let f x = trace "msg" x in f 10 + f 10
因为我们两次调用该函数,所以

打印“msg”两次。取而代之的是,

let f x = trace "msg" x in 2 * f 10

只打印一次“msg”。这仅表明评估的方式不同,而不是结果不同。

在正常的“生产”代码中,程序员不应该依赖调试辅助工具(例如Debug.*模块中的辅助工具来生成消息)。实际上,这会破坏纯函数式编程的许多不错的属性,并且只应用于调试目的。