Haskell 声明中的感叹号是什么意思? [英] What does the exclamation mark mean in a Haskell declaration?

查看:35
本文介绍了Haskell 声明中的感叹号是什么意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我尝试使用真实项目来驱动它来学习 Haskell 时,我遇到了以下定义.我不明白每个参数前面的感叹号是什么意思,我的书似乎没有提到它.

I came across the following definition as I try to learn Haskell using a real project to drive it. 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))

上面的函数 f 在计算时将返回一个thunk":即要执行以计算其值的代码.那时,Foo 还不存在,只有代码.

The function f above, when evaluated, will return a "thunk": that is, the code to execute to figure out its value. At that point, a Foo doesn't even exist yet, just the code.

但在某些时候,有人可能会尝试查看它的内部,可能是通过模式匹配:

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"

这将执行足够的代码来完成它需要的事情,仅此而已.所以它将创建一个带有四个参数的 Foo (因为如果它不存在,你就无法查看它的内部).首先,因为我们正在测试它,所以我们需要一直评估到 4,我们发现它不匹配.

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). The first, since we're testing it, we need to evaluate all the way to 4, where we realize it doesn't match.

第二个不需要评估,因为我们没有测试它.因此,我们不会将 6 存储在该内存位置,而是将代码存储为可能的后续评估,(3+3).只有当有人看它时,它才会变成 6.

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). That will turn into a 6 only if someone looks at it.

然而,第三个参数前面有一个!,所以严格求值:(4+4)被执行,8 存储在该内存位置.

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.

第四个参数也是严格评估的.但这里有点棘手:我们没有完全评估,而只是对弱正常的头部形态进行评估.这意味着我们确定它是 Nothing 还是 Just 的东西,然后存储它,但我们没有进一步.这意味着我们存储的不是 Just 10 而是实际 Just (5+5),让里面的 thunk 没有被评估.知道这一点很重要,尽管我认为这的所有含义都超出了这个问题的范围.

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. That means that we store not Just 10 but actually Just (5+5), leaving the thunk inside unevaluated. This is important to know, though I think that all the implications of this go rather beyond the scope of this question.

如果启用BangPatterns 语言扩展,您可以用同样的方式注释函数参数:

You can annotate function arguments in the same way, if you enable the BangPatterns language extension:

f x !y = x*y

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

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

这篇关于Haskell 声明中的感叹号是什么意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆