[英]Haskell : Will GHC optimize this?
Can GHC simplify id = (\\(a, b) -> (a, b)).(\\(a, b) -> (a, b))
into id = \\(a, b) -> (a, b)
? GHC可以将
id = (\\(a, b) -> (a, b)).(\\(a, b) -> (a, b))
简化为id = \\(a, b) -> (a, b)
?
What about more complicated case : 更复杂的情况呢?
id (Just x) = Just x
id Nothing = Nothing
map f (Just x) = Just (f x)
map _ Nothing = Nothing
Will GHC simplify id . map
GHC会简化
id . map
id . map
into map
? id . map
到map
?
I tried to use plain beta reduction but it looks like these terms are irreducible because of the nasty pattern matching. 我尝试使用普通的beta缩减,但看起来这些术语是不可简化的,因为讨厌的模式匹配。
Therefore I am curious how do GHC's optimization techniques deal with that. 因此,我很好奇GHC的优化技术是如何处理的。
You can ask these questions of ghc by running it with -ddump-simpl
. 您可以通过使用
-ddump-simpl
运行它来询问ghc的这些问题。 This will cause ghc to dump the "core" code that it compiles programs into. 这将导致ghc转储它编译程序的“核心”代码。 Core is an intermediate language between the part of the compiler that reasons about Haskell code and the part of the compiler that transforms that code into machine code.
Core是编译器的一部分介于Haskell代码之间的中间语言,也是编译器将该代码转换为机器代码的部分。
When I compiled the following with -O2 -ddump-simpl
the results surprised me. 当我使用
-O2 -ddump-simpl
编译以下内容时,结果让我感到惊讶。
tupid1 :: (a, b) -> (a, b)
tupid1 = (\(a, b) -> (a, b))
tupid2 :: (a, b) -> (a, b)
tupid2 = (\(a, b) -> (a, b)) . (\(a, b) -> (a, b))
The resulting core for tupid1
makes a new specialized identity function. 由此产生的
tupid1
核心构成了一个新的专用身份函数。
-- RHS size: {terms: 4, types: 7, coercions: 0}
tupid1 :: forall a_aqo b_aqp. (a_aqo, b_aqp) -> (a_aqo, b_aqp)
[GblId,
Arity=1,
Caf=NoCafRefs,
Str=DmdType <S,1*U(U,U)>m,
Unf=Unf{Src=InlineStable, TopLvl=True, Value=True, ConLike=True,
WorkFree=True, Expandable=True,
Guidance=ALWAYS_IF(arity=1,unsat_ok=True,boring_ok=True)
Tmpl= \ (@ a_ayd)
(@ b_aye)
(ds_dIl [Occ=Once] :: (a_ayd, b_aye)) ->
ds_dIl}]
tupid1 = \ (@ a_ayd) (@ b_aye) (ds_dIl :: (a_ayd, b_aye)) -> ds_dIl
In core the polymorphic type arguments to functions are represented as explicit arguments. 在核心中,函数的多态类型参数表示为显式参数。
tupid1
takes two of these type arguments, named a_ayd
and b_aye
, for the two type variables a
and b
in its signature. tupid1
为其签名中的两个类型变量a
和b
采用其中两个类型参数,名为a_ayd
和b_aye
。 It also takes a term ds_dIl
that has the type of a tuple of those two types ( ds_dIl :: (a_ayd, b_aye)
) and returns it unmodified. 它还需要一个术语
ds_dIl
,它具有这两种类型的元组类型( ds_dIl :: (a_ayd, b_aye)
)并且不加修改地返回它。
The surprising result is tupid2
... 令人惊讶的结果是
tupid2
......
-- RHS size: {terms: 1, types: 0, coercions: 0}
tupid2 :: forall a_aqm b_aqn. (a_aqm, b_aqn) -> (a_aqm, b_aqn)
[GblId,
Arity=1,
Caf=NoCafRefs,
Str=DmdType <S,1*U(U,U)>m,
Unf=Unf{Src=InlineStable, TopLvl=True, Value=True, ConLike=True,
WorkFree=True, Expandable=True,
Guidance=ALWAYS_IF(arity=1,unsat_ok=True,boring_ok=True)
Tmpl= \ (@ a_axZ) (@ b_ay0) (x_aIw [Occ=Once] :: (a_axZ, b_ay0)) ->
x_aIw}]
tupid2 = tupid1
... which ghc simplifies to tupid1
! ...哪个ghc简化为
tupid1
! How it deduces that is beyond my immediate knowledge or ability to discover. 如何推断这是超出我的直接知识或发现的能力。
The identity example for Maybe
Maybe
的标识示例
maybeid :: Maybe a -> Maybe a
maybeid (Just x) = Just x
maybeid Nothing = Nothing
Is also simplified to an identity function with no pattern matching 也简化为没有模式匹配的身份函数
-- RHS size: {terms: 3, types: 4, coercions: 0}
maybeid :: forall a_aqn. Maybe a_aqn -> Maybe a_aqn
[GblId,
Arity=1,
Caf=NoCafRefs,
Str=DmdType <S,1*U>,
Unf=Unf{Src=InlineStable, TopLvl=True, Value=True, ConLike=True,
WorkFree=True, Expandable=True,
Guidance=ALWAYS_IF(arity=1,unsat_ok=True,boring_ok=True)
Tmpl= \ (@ a_aqI) (ds_dIq [Occ=Once] :: Maybe a_aqI) -> ds_dIq}]
maybeid = \ (@ a_aqI) (ds_dIq :: Maybe a_aqI) -> ds_dIq
The core for map
for Maybe
isn't interesting for this question 对于这个问题,
Maybe
map
核心并不有意思
maybemap :: (a -> b) -> Maybe a -> Maybe b
maybemap f (Just x) = Just (f x)
maybemap _ Nothing = Nothing
But if it's composed with maybeid
但如果它是由
maybeid
组成的
maybeidmap :: (a -> b) -> Maybe a -> Maybe b
maybeidmap f = maybeid . maybemap f
ghc simplifies it to maybemap
ghc将其简化为
maybemap
-- RHS size: {terms: 1, types: 0, coercions: 0}
maybeidmap
:: forall a_aqp b_aqq.
(a_aqp -> b_aqq) -> Maybe a_aqp -> Maybe b_aqq
[GblId,
Arity=2,
Caf=NoCafRefs,
Str=DmdType <L,1*C1(U)><S,1*U>,
Unf=Unf{Src=InlineStable, TopLvl=True, Value=True, ConLike=True,
WorkFree=True, Expandable=True,
Guidance=ALWAYS_IF(arity=0,unsat_ok=True,boring_ok=True)
Tmpl= maybemap}]
maybeidmap = maybemap
And it does the same thing if id
is composed with f
. 如果
id
由f
组成,它也会做同样的事情。
maybemapid :: (a -> b) -> Maybe a -> Maybe b
maybemapid f = maybemap (id . f)
The composition with the identity function is removed and the whole function simplifies to maybemap
删除具有身份功能的组合,整个功能简化为可能
maybemap
-- RHS size: {terms: 1, types: 0, coercions: 0}
maybemapid
:: forall a_aqq b_aqr.
(a_aqq -> b_aqr) -> Maybe a_aqq -> Maybe b_aqr
[GblId,
Arity=2,
Caf=NoCafRefs,
Str=DmdType <L,1*C1(U)><S,1*U>,
Unf=Unf{Src=InlineStable, TopLvl=True, Value=True, ConLike=True,
WorkFree=True, Expandable=True,
Guidance=ALWAYS_IF(arity=2,unsat_ok=True,boring_ok=False)
Tmpl= \ (@ a_ar2)
(@ b_ar3)
(f_aqL [Occ=Once!] :: a_ar2 -> b_ar3)
(eta_B1 [Occ=Once!] :: Maybe a_ar2) ->
case eta_B1 of _ [Occ=Dead] {
Nothing -> GHC.Base.Nothing @ b_ar3;
Just x_aqJ [Occ=Once] -> GHC.Base.Just @ b_ar3 (f_aqL x_aqJ)
}}]
maybemapid = maybemap
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.