$(美元)和$之间有什么区别!(美元感叹号)

Jel*_*sen 27 syntax haskell

任何人都可以解释Haskell在运算符($)($!)(美元符号与美元符号感叹号)之间的区别吗?

$!到目前为止,我还没有看到任何地方的使用,但在浏览Haskell 参考时,我注意到它的存在,并且它具有完全相同的定义$.在Haskell解释器(GHCi)中尝试一些简单的语句时,我找不到任何差异,在搜索时也无法在列出的顶级教程中找到对运算符的任何引用haskell tutorial.

所以,出于好奇,有什么区别,如果有的话?

Tom*_*rst 44

($!)是严格的功能应用.也就是说,它在评估函数之前评估参数.

这与Haskell中的正常延迟函数应用程序相反,例如,f x或者f $ x,它首先开始评估函数f,并且仅在x需要时计算参数.

例如,succ (1 + 2)1 + 2通过创建thunk 来延迟添加,并首先开始评估succ.只有在需要succ的参数时才会1 + 2进行评估.

但是,如果您确定始终需要函数的参数,则可以使用($!),首先将参数计算为弱头正规形式,然后输入函数.这样,你就不会创建一大堆thunks,这样可以更有效率.在此示例中,succ $! 1 + 2首先计算3然后输入函数succ.

请注意,用严格的函数应用程序替换普通函数应用程序并不总是安全的.例如:

ghci> const 1 (error "noo!")
1
ghci> const 1 $! (error "noo!")
*** Exception: noo!
Run Code Online (Sandbox Code Playgroud)

  • 好吧,消息的打印是副作用,但重点是"错误"是⊥(底部).就像一个永无止境的计算是⊥.如果使用`seq`评估,,程序的语义会发生变化.这就是为什么你应该小心使用`seq`和`($!)`之类的东西,它可以提高(或降低)程序的效率,但它也可能使它崩溃到通常不应该的地方. (8认同)
  • 最后一个例子更多的是关于"错误"的副作用.功能语义永远不会受到刘海的伤害(对于'par`和`seq`也是如此).放刘海有时会增加速度/记忆力,有时会减少.在某些特殊情况下,它可能导致永无止境的计算`const 1 $!(最后[1 ..])`. (4认同)

Fra*_*sco 7

请参阅 seq函数,该函数强制评估值.$!根据seq定义.

是一篇博文,展示了其使用的一些细微差别.