我碰到下面的定义之际,我尝试使用一个真正的项目带动它来学习哈斯克尔。我不明白在每个参数前面的感叹号手段和我的书似乎没有提到它。

data MidiMessage = MidiMessage !Int !MidiMessage
有帮助吗?

解决方案

这是一个严格的声明。基本上,这意味着它必须进行评估,以什么所谓的“弱普通打印头的形式”创建数据结构值时。让我们来看一个例子,这样我们就可以看到刚才这意味着什么:

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

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

在功能f以上,进行评价时,将返回“咚”:即,要执行的代码,以计算出其值。在这一点上,一个富甚至不存在尚未,只是的代码。

但在某些时候可能有人会尝试看看里面,可能是通过模式匹配:

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

这是要执行足够的代码做什么需要,并没有更多的。因此,它会创建四个参数一个Foo(因为你不能看里面没有它存在的)。第一,因为我们正在测试它,我们需要所有4的方式,我们意识到它不符合评估。

第二并不需要进行评估,因为我们没有测试它。因此,而不是6被存储在该存储单元中,我们只存储可能以后评估代码,(3+3)。这会变成一个6只,如果有人着眼于它。

第三个参数,但是,有在它前面一个!,所以严格评价:执行(4+4),和8被存储在该存储器位置

第四个参数也严格评价。但这里的地方变得有点棘手:我们正在评估并不完全,但只有微弱的正常头型。这意味着我们弄清楚它是否NothingJust东西,商店,但我们就不再继续。这意味着,我们店里没有Just 10但实际上Just (5+5),留下内未评估在thunk。这是重要的是知道,但我认为这一切的含义志不超出了这个问题的范围。

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

f x !y = x*y

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

其他提示

一个简单的方法来看到严格和非严格构造器参数之间的区别是它们的行为,当他们是不确定的。给定

data Foo = Foo Int !Int

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

由于非严格的参数不被second评价,传入undefined不会引起一个问题:

> second (Foo undefined 1)
1

但严格的论证不能undefined,即使我们不使用值:

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

我相信这是一个严密的注释。

Haskell是一个纯粹的并且懒惰功能性的语言,但有时lazyness的开销可以是过多或浪费的。所以,对付的是,你可以要求编译器的参数充分评估的功能,而不是围绕解析的thunk。

还有这个页面上的更多信息:性能/严

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top