C союзы не помечены как союзы, см. википедию на этом . В haskell MyUnion будет занимать больше памяти, чем один необработанный (без упаковки) 64-битный int. В GHC это был бы специальный указатель на thunk или значение: thunk - это когда ленивый MyUnion еще не был оценен, значение для того, когда он был оценен, а размер памяти, на который указывают, может варьироваться (в отличие от объединений в с). «Специальный» указатель будет использовать обычно нулевые младшие биты 64-разрядного указателя, чтобы указать, известно ли это как значение C или I, чтобы объединить тегирование с указателем.
Менее ленивое объявление в Haskell можно сделать с помощью
data MyUnion1 = I !Int | C !Char
data MyUnion2 = I {-# UNPACK #-} !Int | C {-# UNPACK #-} !Char
Где "!" указывает, что значение никогда не сохраняется как неоцененный раздел. Комментарий к прагме компилятора UNPACK просит GHC хранить необработанное распакованное значение рядом с тегом вместо хранения указателя на Int или Char. Таким образом, MyUnion2 может занимать меньше памяти и будет строгим, а не ленивым.
Кроме того, я должен подчеркнуть, что "char" из C - это один байт со знаком, в то время как "Char" в Haskell - это полная кодовая точка Unicode (значение от 0 до 1114111). Чтобы хранить символ C "в Haskell, вы должны использовать CChar .
У вас есть союзы, используемые в C, и вам нужно их сериализовать и десериализовать? У вас уже есть двоичный формат, используемый C? Если вам нужно изобрести бинарный формат, вам нужно разработать тег, чтобы сделать Haskell счастливым. В вашем примере на C нет способа определить, было ли значение «создано» с помощью int или char, в то время как MyUnion в Haskell может определить, было ли значение создано с помощью I или C.
Тип C, который вы написали, также довольно опасен, как будто я пишу в однобайтовый "char" и читаю многобайтовый "int", остальные байты в "int", вероятно, не определены.