Подтвердить что ты не робот

Создает ли GHC новую копию объекта при деконструировании и восстановлении?

Если у меня есть тип типа data T = T Int String и такая функция:

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

После деконструкции в сопоставлении шаблонов GHC создает новый объект T, содержащий ссылки на те же Int и String? Или он возвращает тот же самый объект (с тем же адресом памяти), который он получил? Я понимаю, что они семантически эквивалентны, мне просто интересно.

4b9b3361

Ответ 1

В общем случае GHC будет выделять новое значение, а не повторно использовать аргумент в этой ситуации. В этом конкретном случае вы могли бы написать что-то вроде

f :: T -> T
f [email protected](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, и вы не можете просто повторно использовать аргумент, потому что результат имеет другой тип. Насколько я знаю, нет способа сказать GHC повторно использовать аргумент в этом случае, кроме unsafeCoerce.

Ответ 2

Вы можете проверить это достаточно легко с помощью -ddump-simpl. Выделение значения ADT будет отображаться как приложение конструктора данных.

В этом случае GHC обнаруживает, что он может повторно использовать значение, и даже если ему не нужно выполнять сопоставление шаблонов:

module I where

data T = T Int String

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

-

[email protected]:/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 с несколькими конструкторами.