如果我有类似data T = T Int String
的类型和类似的函数:
identity :: T -> T
identity (T a b) = T a b
在模式匹配中解构后,GHC是否创建了一个包含对同一个Int和String的引用的新T对象?或者它返回它收到的完全相同的对象(具有相同的内存地址)?我知道他们在语义上是等同的,我只是很好奇。
答案 0 :(得分:15)
一般情况下,GHC会分配一个新值,而不是在那种情况下重用该参数。在这种特殊情况下,您可以编写类似
的内容f :: T -> T
f t@(T x y) = t
显式重用参数。不幸的是,在其中一个您真正想要这个的情况下 -
fmap :: (a -> b) -> Either e a -> Either e b
fmap f (Right x) = Right (f x)
fmap f (Left x) = Left x
- GHC将分配一个新的Left
值,您不能简单地重用该参数,因为结果具有不同的类型。据我所知,除了unsafeCoerce
之外,没有办法告诉GHC在这种情况下重用参数。
答案 1 :(得分:15)
您可以使用-ddump-simpl
轻松地对此进行测试。 ADT值的分配将显示为数据构造函数的应用程序。
在这种情况下,GHC确实发现它可以重用该值,即使它不必执行模式匹配:
module I where
data T = T Int String
identity :: T -> T
identity (T a b) = T a b
-
rwbarton@morphism:/tmp$ ghc -ddump-simpl I
[1 of 1] Compiling I ( I.hs, I.o )
==================== Tidy Core ====================
Result size of Tidy Core = {terms: 3, types: 3, coercions: 0}
I.identity :: I.T -> I.T
[GblId, Arity=1, Caf=NoCafRefs, Str=DmdType]
I.identity = \ (ds_dHN :: I.T) -> ds_dHN
即使没有启用优化,也会发生这种情况,并且它也适用于具有多个构造函数的ADT。