为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

当我尝试使用真实的项目来驱动Haskell时,遇到了以下定义。我不明白每个论点前面的感叹号的含义,而且我的书中似乎都没有提到它。data MidiMessage = MidiMessage !Int !MidiMessage
查看完整描述

3 回答

?
holdtom

TA贡献1805条经验 获得超10个赞

这是一个严格的声明。基本上,这意味着在创建数据结构值时,必须将其评估为所谓的“弱头范式”。让我们看一个示例,以便我们可以看到这意味着什么:


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还是Just某种东西,并将其存储起来,但是我们走得更远了。这意味着我们Just 10实际上不是存储而是Just (5+5)保留其中的杂物未被评估。要知道这一点很重要,尽管我认为这的所有含义都超出了此问题的范围。


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


f x !y = x*y

f (1+1) (2+2)会归还笨拙的(1+1)*4。


查看完整回答
反对 回复 2019-12-09
?
青春有我

TA贡献1784条经验 获得超8个赞

我相信这是严格的注解。

Haskell是一种纯粹且懒惰的函数式语言,但有时懒惰的开销可能过多或浪费。因此,为了解决这个问题,您可以要求编译器完全评估函数的参数,而不是解析乱码。


查看完整回答
反对 回复 2019-12-09
  • 3 回答
  • 0 关注
  • 892 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信