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

Ram*_*eka 18 haskell pattern-matching ghc

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

identity :: T -> T
identity (T a b) = T a b
Run Code Online (Sandbox Code Playgroud)

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

sha*_*haf 15

通常,GHC将分配一个新值,而不是在那种情况下重用该参数.在这种特殊情况下,您可以编写类似的内容

f :: T -> T
f t@(T x y) = t
Run Code Online (Sandbox Code Playgroud)

显式重用参数.不幸的是,在其中一个你真的想要这个的情况下 -

fmap :: (a -> b) -> Either e a -> Either e b
fmap f (Right x) = Right (f x)
fmap f (Left x) = Left x
Run Code Online (Sandbox Code Playgroud)

- GHC将分配一个新Left值,您不能简单地重用该参数,因为结果具有不同的类型.据我所知,除了这种情况外,没有办法告诉GHC在这种情况下重用参数unsafeCoerce.

  • @Ramith遗憾地摧毁了懒惰; 路径下到叶节点的所有调用都必须等待最终调用返回,然后才能知道它们是否返回对现有构造函数节点的引用或分配新节点,这意味着强制执行根节点步强迫一切.因此,如果您想要在这些属性之间进行选择(懒惰与避免重建相同的树),则需要明确编程(例如通过Maybe(树a)帮助程序)而不是编译器的隐式行为. (4认同)

Rei*_*ton 15

你可以很容易地测试这个-ddump-simpl.ADT值的分配将显示为数据构造函数的应用程序.

在这种情况下,GHC确实发现它可以重用该值,甚至它不必执行模式匹配:

module I where

data T = T Int String

identity :: T -> T
identity (T a b) = T a b
Run Code Online (Sandbox Code Playgroud)

-

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
Run Code Online (Sandbox Code Playgroud)

即使没有启用优化,也会发生这种情况,并且它也适用于具有多个构造函数的ADT.