在Haskell中是否存在完全应用的curried函数thunk?

Tho*_*asH 4 haskell

换句话说:

我可以在不进行评估的情况下将所有参数应用于curried函数吗?所以我还有一个函数值,而不是计算的结果?

例:

add x y = x + y
add1 = add 3   {- add1 is a function -}
add2 = add1 4  {- add2 is 7, but I would like to have a function 
                  I can call with no arguments!? -}
Run Code Online (Sandbox Code Playgroud)

原因是传递完全绑定的函数,并且可以在任意情况下调用,而无需提供其他参数.

请不要欺骗(比如在呼叫站点提供伪造的最后一个参数,如1或True).

dfe*_*uer 10

函数总是带参数.没有参数的那个不是函数.这里唯一的小窍门是Haskell认为值的一些东西,在系统FC中,是函数.例如7有类型Num a => a,这意味着在Haskell中它是一个多态数字,但在System FC中它是一个函数,它接受一个Num a字典并生成一个a.所以你可以得到你所要求的.

但是,你所要求的似乎并不是你想要的!计算昂贵的事实并不意味着你应该把它作为一个函数的结果

x = really expensive computation
Run Code Online (Sandbox Code Playgroud)

实际上没有计算x.只有当你检查的值x(通过模式匹配,或者seq,或者evaluate,等)也x得到评估,而且当时它只是尽可能必要的评估.

评论:

好的,所以GHCi背叛了我,让我相信add1 4立即被评估为7,而在正常的程序运行中情况并非如此?!

不!您输入add1 4了GHCi提示符.因此,GHCi得出结论,你希望它达到print这个价值.为了得到print一个数字,需要计算所有数字,并且首先需要计算数字本身!如果你想深入了解,你可以使用GHCi :print或:sprint命令,它可以让你检查未评估或部分评估的东西.

Prelude> let foo = (1+2, 3+4) :: (Int, Int)
Prelude> :print foo
foo = ((_t3::Int),(_t4::Int))
Prelude> fst foo
3
Prelude> :print foo
foo = (3,(_t5::Int))
Prelude> snd foo
7
Prelude> :print foo
foo = (3,7)
Run Code Online (Sandbox Code Playgroud)

注意:懒洋洋地拖延事情可能会对性能产生不良影响.GHC在编译代码中花了很大的篇幅来确定何时可以使它们严格而不影响程序的含义而不会导致其他性能问题.这个编译器传递称为"需求分析",它是"严格性分析"的一种特殊形式.

  • @ThomasH,是的.thunk实际上只会在第一次被迫时做一些有趣的事情; 后续访问将使用存储的结果. (2认同)