内部爆炸模式是否总是在Haskell中强制外部构造函数? [英] Do inner bang patterns always force outer constructors in 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 仅谈论
let
绑定(例如 https://prime.haskell.org/wiki/BangPatterns#Thebasicidea说
- 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
inGHCi
, 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屋!
- because it's like
- 因为它就像