简体   繁体   English

Haskell 声明中的感叹号是什么意思?

[英]What does the exclamation mark mean in a Haskell declaration?

I came across the following definition as I try to learn Haskell using a real project to drive it.当我尝试使用真实项目来驱动它来学习 Haskell 时,我遇到了以下定义。 I don't understand what the exclamation mark in front of each argument means and my books didn't seem to mention it.我不明白每个参数前面的感叹号是什么意思,我的书似乎没有提到它。

data MidiMessage = MidiMessage !Int !MidiMessage

It's a strictness declaration.这是一个严格性声明。 Basically, it means that it must be evaluated to what's called "weak head normal form" when the data structure value is created.基本上,这意味着在创建数据结构值时必须将其评估为所谓的“弱头范式”。 Let's look at an example, so that we can see just what this means:让我们看一个例子,这样我们就能明白这意味着什么:

data Foo = Foo Int Int !Int !(Maybe Int)

f = Foo (2+2) (3+3) (4+4) (Just (5+5))

The function f above, when evaluated, will return a "thunk": that is, the code to execute to figure out its value.上面的函数f在计算时将返回一个“thunk”:即要执行以计算其值的代码。 At that point, a Foo doesn't even exist yet, just the code.那时,Foo 还不存在,只有代码。

But at some point someone may try to look inside it, probably through a pattern match:但在某些时候,有人可能会尝试查看它的内部,可能是通过模式匹配:

case f of
     Foo 0 _ _ _ -> "first arg is zero"
     _           -> "first arge is something else"

This is going to execute enough code to do what it needs, and no more.这将执行足够的代码来完成它所需要的,仅此而已。 So it will create a Foo with four parameters (because you can't look inside it without it existing).所以它将创建一个带有四个参数的 Foo(因为如果它不存在,你就无法查看它的内部)。 The first, since we're testing it, we need to evaluate all the way to 4 , where we realize it doesn't match.首先,因为我们正在测试它,所以我们需要一直评估到4 ,我们意识到它不匹配。

The second doesn't need to be evaluated, because we're not testing it.第二个不需要评估,因为我们没有测试它。 Thus, rather than 6 being stored in that memory location, we'll just store the code for possible later evaluation, (3+3) .因此,我们不会将6存储在该内存位置,而是只存储代码以供以后评估, (3+3) That will turn into a 6 only if someone looks at it.只有当有人看它时,它才会变成 6。

The third parameter, however, has a !然而,第三个参数有一个! in front of it, so is strictly evaluated: (4+4) is executed, and 8 is stored in that memory location.在它前面,so 是严格求值的: (4+4)被执行, 8存储在那个内存位置。

The fourth parameter is also strictly evaluated.第四个参数也被严格评估。 But here's where it gets a bit tricky: we're evaluating not fully, but only to weak normal head form.但这里有点棘手:我们没有完全评估,而只是对弱正常的头部形态进行评估。 This means that we figure out whether it's Nothing or Just something, and store that, but we go no further.这意味着我们要弄清楚它是Nothing还是Just something,然后将其存储起来,但我们不会再进一步​​了。 That means that we store not Just 10 but actually Just (5+5) , leaving the thunk inside unevaluated.这意味着我们不仅存储Just 10而且实际上存储Just (5+5) ,让里面的 thunk 不求值。 This is important to know, though I think that all the implications of this go rather beyond the scope of this question.知道这一点很重要,尽管我认为这的所有含义都超出了这个问题的范围。

You can annotate function arguments in the same way, if you enable the BangPatterns language extension:如果您启用BangPatterns语言扩展,您可以以相同的方式注释函数参数:

f x !y = x*y

f (1+1) (2+2) will return the thunk (1+1)*4 . f (1+1) (2+2)将返回 thunk (1+1)*4

A simple way to see the difference between strict and non-strict constructor arguments is how they behave when they are undefined.查看严格和非严格构造函数参数之间差异的一种简单方法是它们在未定义时的行为。 Given给定的

data Foo = Foo Int !Int

first (Foo x _) = x
second (Foo _ y) = y

Since the non-strict argument isn't evaluated by second , passing in undefined doesn't cause a problem:由于非严格参数不是由second计算的,传入undefined不会导致问题:

> second (Foo undefined 1)
1

But the strict argument can't be undefined , even if we don't use the value:但是严格参数不能是undefined ,即使我们不使用该值:

> first (Foo 1 undefined)
*** Exception: Prelude.undefined

I believe it is a strictness annotation.我相信这是一个严格的注释。

Haskell is a pure and lazy functional language, but sometimes the overhead of lazyness can be too much or wasteful. Haskell 是一种纯粹且懒惰的函数式语言,但有时懒惰的开销可能过多或浪费。 So to deal with that, you can ask to compiler to fully evaluate the arguments to a function instead of parsing thunks around.因此,为了解决这个问题,您可以要求编译器完全评估函数的参数,而不是解析周围的 thunk。

There's more information on this page: Performance/Strictness .此页面上有更多信息: Performance/Strictness

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM