内部爆炸模式是否总是在Haskell中强制外部构造函数? [英] Do inner bang patterns always force outer constructors in Haskell?

查看:74
本文介绍了内部爆炸模式是否总是在Haskell中强制外部构造函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Haskell中,曾经存在过一种数据类型的情况

In Haskell, is there ever a situation where for a data type

{-# LANGUAGE BangPatterns #-}
import Control.DeepSeq

data D = D Int

实例

instance NFData D where
  rnf (D !_) = ()

的效果可能与带有另一个外部!的实例的效果不同:

can have a different effect than the instance with another outer !:

instance NFData D where
  rnf !(D !_) = ()

我的研究:

  • https://downloads.haskell.org/~ghc/8.6.3/docs/html/users_guide/glasgow_exts.html#bang-patterns-informal only talks about let bindings (like this answer), which I think doesn't apply for function pattern matches like this.
  • https://prime.haskell.org/wiki/BangPatterns#Thebasicidea says

只有在变量或通配符模式之前,爆炸才真正起作用

A bang only really has an effect if it precedes a variable or wild-card pattern

在强制评估的模式前加一个爆炸没有任何作用

putting a bang before a pattern that forces evaluation anyway does nothing

我认为

  • rnf (D _)已经强制进行评估
    • 因为它就像rnf x = case x of D _ -> ...
    • rnf (D _) already forces evaluation anyway
      • because it's like rnf x = case x of D _ -> ...

      所以我认为不,这两个总是相等的,但是无论如何,我都要求提供一个超清晰的答案来推荐人们.

      So I think no, these two are always equivalent, but I'm asking anyway to have one super clear answer to refer people to.

      推荐答案

      实际上,这是正确的.我们可以看到在GHCi中使用:sprint进行了评估,向我们展示了已评估了哪些thunk.

      Indeed this is correct. We can see what is evaluated using :sprint in GHCi, which shows us what thunks have been evaluated.

      没有爆炸图案:

      λ data D = D Int
      λ d1 = D 1
      λ :sprint d1
      d1 = _
      λ f1 (D _) = 0
      λ f1 d1
      0
      λ :sprint d1
      d1 = <D> _ -- Only D evaluated
      

      具有内部爆炸样式:

      λ d2 = D 2
      λ :sprint d2
      d2 = _
      λ f2 (D !_) = 0
      λ f2 d2
      0
      λ :sprint d2
      d2 = <D> 2 -- Everything evaluated
      

      具有外部爆炸样式:

      λ d3 = D 3
      λ :sprint d3
      d3 = _
      λ f3 !(D _) = 0
      λ f3 d3
      0
      λ :sprint d3
      d3 = <D> _ -- Only D evaluated
      

      具有内部和外部爆炸样式:

      With an inner and outer bang patterns:

      λ d4 = D 4
      λ :sprint d4
      d4 = _
      λ f4 !(D !_) = 0
      λ f4 d4
      0
      λ :sprint d4
      d4 = <D> 4 -- Everything evaluated
      

      由此我们可以轻松地看到!(D !_)(D !_)模式是等效的,而且!(D ...)形式的模式是多余的.

      From this we can easily see that the patterns !(D !_) and (D !_) are equivalent, and moreover that patterns of the form !(D ...) are redundant.

      这篇关于内部爆炸模式是否总是在Haskell中强制外部构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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