Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

If I have a type like data T = T Int String and a function like so:

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

After the deconstruction in the pattern matching, does GHC create a new T object containing references to the same Int and String? Or does it return the exact same object (with the same memory address) it received? I understand they're semantically equivalent, I'm just curious.

like image 783
Ramith Jayatilleka Avatar asked Jun 28 '15 22:06

Ramith Jayatilleka


People also ask

How are objects assigned and copied in C++?

Objects are assigned and copied by reference. In other words, a variable stores not the “object value”, but a “reference” (address in memory) for the value. So copying such a variable or passing it as a function argument copies that reference, not the object itself.

What happens when you copy an object with a reference?

When an object variable is copied, the reference is copied, but the object itself is not duplicated. Now we have two variables, each storing a reference to the same object: As you can see, there’s still one object, but now with two variables that reference it.

How to replicate the structure of an existing object?

But if we really want that, then we need to create a new object and replicate the structure of the existing one by iterating over its properties and copying them on the primitive level. Also we can use the method Object.assign for that. Object.assign( dest, [ src1, src2, src3 ...]) The first argument dest is a target object.

What happens when you copy an object with two variables?

When an object variable is copied, the reference is copied, but the object itself is not duplicated. Now we have two variables, each storing a reference to the same object: As you can see, there’s still one object, but now with two variables that reference it. We can use either variable to access the object and modify its contents:


1 Answers

In general GHC will allocate a new value rather than reuse the argument in that situation. In this particular case you could write something like

f :: T -> T
f t@(T x y) = t

to explicitly reuse the argument. Unfortunately, in one of the cases where you'd really want this --

fmap :: (a -> b) -> Either e a -> Either e b
fmap f (Right x) = Right (f x)
fmap f (Left x) = Left x

-- GHC will allocate a new Left value, and you can't simply reuse the argument, because the result has a different type. As far as I know there's no way to tell GHC to reuse the argument in this case other than unsafeCoerce.

like image 94
shachaf Avatar answered Oct 03 '22 15:10

shachaf