https://stackoverflow.com/a/2787560/645703说:
($!)是严格的功能应用程序。也就是说,它评估了 在评估函数之前的参数。
我知道!(感叹号)是Haskell中的严格声明。看起来两者都有严格应用的东西,但有什么区别?
答案 0 :(得分:2)
!
扩展程序启用的 BangPatterns
始终采用模式,在绑定之前,如下所示:
add :: Int -> Int -> Int
add !a b = a + b
这意味着"如果执行试图强制执行此模式案例,则在评估模式的右侧之前将!-ed绑定减少为弱头正常形式"
f $! x
表示"如果执行试图强迫这个" f $! X"表达,然后通过首先减少" x"弱头正常形式,然后应用" f"减少" x" &#34 ;.
在这两种情况下,请注意严格注释仅表示条件语句。如果我有一个f $! x
(其中x
可能是一个复杂计算的thunk),如果执行从未尝试强制f $! x
,那么当然没有任何内容会被评估。
答案 1 :(得分:1)
如果传递undefined
会导致异常,则会被视为“严格”,如:
> :set -XBangPatterns
> let foo b x = if b then show x else "ignore x"
> let foo' b !x = if b then show x else "ignore x"
> foo False undefined
"ignore x"
> foo' False undefined
"*** Exception: Prelude.undefined
但我们不能在函数声明之外使用!
。因此,我们需要使用$!
,就像您提供的链接中的示例一样(在这种情况下,它用于替换$
):
> const 1 $ undefined
1
> const 1 $! undefined
*** Exception: Prelude.undefined
您还会注意到,对于!
,您需要使用BangPatterns语言扩展,但不能使用$!
。注意$!
是以!
实现的(虽然以一种有点奇怪的方式引用我认为必须是issue #2273),这也很有用。
请参阅$! implementation in Prelude:
($!) :: (a -> b) -> a -> b
f $! x = let !vx = x in f vx -- see #2273