GHC 在解构和重建对象时是否会创建对象的新副本?

Does GHC make a new copy of an object when deconstructing and reconstructing it?

如果我有像 data T = T Int String 这样的类型和像这样的函数:

identity :: T -> T
identity (T a b) = T a b

在模式匹配中解构之后,GHC 是否会创建一个新的T 对象,其中包含对相同Int 和String 的引用?或者它 return 它接收到的是完全相同的对象(具有相同的内存地址)吗?我知道它们在语义上是等价的,我只是好奇。

一般来说,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 在这种情况下重用该参数

您可以使用 -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。