这是一个严格的声明。基本上,这意味着在创建数据结构值时必须将其评估为所谓的“弱头范式”。让我们看一个例子,以便我们了解这意味着什么:
data Foo = Foo Int Int !Int !(Maybe Int)
f = Foo (2+2) (3+3) (4+4) (Just (5+5))
功能f
上面的计算时,将返回一个“thunk”:即执行以计算出其值的代码。那时,Foo 甚至还不存在,只有代码。
但在某些时候,有人可能会尝试查看它的内部,可能是通过模式匹配:
case f of
Foo 0 _ _ _ -> "first arg is zero"
_ -> "first arge is something else"
这将执行足够的代码来完成其需要的操作,仅此而已。因此它将创建一个带有四个参数的 Foo (因为如果它不存在,你就无法查看它的内部)。首先,由于我们正在测试它,因此我们需要一路评估4
,我们意识到它不匹配。
第二个不需要评估,因为我们没有测试它。因此,而不是6
存储在该内存位置中,我们将只存储代码以供以后可能的评估,(3+3)
。只有当有人看它时,它才会变成6。
然而,第三个参数有一个!
在它前面,所以被严格评估:(4+4)
被执行,并且8
存储在该内存位置。
第四个参数也经过严格评估。但这是有点棘手的地方:我们没有完全评估,而只是针对较弱的正常头部形状。这意味着我们要弄清楚它是否Nothing
or Just
一些东西,并将其存储起来,但我们不再继续。这意味着我们不存储Just 10
但实际上Just (5+5)
,让里面的 thunk 未被评估。知道这一点很重要,尽管我认为这一点的所有含义都超出了这个问题的范围。
如果启用了,您可以以相同的方式注释函数参数BangPatterns
语言扩展:
f x !y = x*y
f (1+1) (2+2)
将返回 thunk(1+1)*4
.