与Haskell的外国金融机构的联合和类型**?

与Haskell的外国金融机构的联合和类型**?,haskell,ffi,discriminated-union,Haskell,Ffi,Discriminated Union,我需要知道如何使用FFI解析并集和类型**(例如int**)? 我知道我需要一个结构的可存储实例,我也可以将它用于联合吗 这样的联盟: typedef union { int i; char c; } my_union; 这在Haskell中通常表示为: data MyUnion = I CInt | C CChar 我的问题是,您将如何处理(定义可存储的实例) 我的联盟变成了我的联盟?据我所知,我的工会 将占用内存中的sizeof(int)字节,即它的最大大小 成员。因

我需要知道如何使用FFI解析并集和类型**(例如int**)? 我知道我需要一个结构的可存储实例,我也可以将它用于联合吗

这样的联盟:

typedef union {
     int i;
     char c;
} my_union;
这在Haskell中通常表示为:

data MyUnion = I CInt | C CChar
我的问题是,您将如何处理(定义可存储的实例) 我的联盟变成了我的联盟?据我所知,我的工会 将占用内存中的sizeof(int)字节,即它的最大大小 成员。因此,为了存储这些信息,我们可以写一些如下的内容:

instance Storable myUnion where
     size _ = #{size my_union} -- <-- hsc2hs shortcut
     alignment _ = alignment undefined::CInt -- <-- What should this really be?
     peek ptr = do -- <-- How are you supposed to know which element to extract?
     poke ptr (I i) =  poke ptr i -- <-- Or should this be #{poke my_union, i} ptr i ?
     poke ptr (C c) = poke ptr c
实例可存储myUnion,其中

size=#{size my_union}--即使在C语言中,如果给您一个:

typedef union {
     int i;
     char c;
} my_union;
C解决方案是添加一个额外的成员来承载该类型

typedef struct {
     int type;
     union {
          int i;
          char c;
     } my_union;
} my_tagged_union;

C活接头不是带标签的活接头,请参见。在haskell中,MyUnion将占用比单个原始(未装箱)64位int更多的内存。在GHC中,它将是指向thunk或值的特殊指针:thunk是指惰性MyUnion尚未求值时,该值是指已求值时,指向的内存大小可以不同(与C中的Union不同)。“特殊”指针将使用64位指针通常为零的低位来指示它是已知的C值还是I值,从而将标记与指针结合起来

在Haskell中,可以使用

data MyUnion1 = I !Int | C !Char
data MyUnion2 = I {-# UNPACK #-} !Int | C {-# UNPACK #-} !Char
其中“!”表示该值从未存储为未计算的thunk。解包编译器pragma注释要求GHC将原始未装箱值存储在标记旁边,而不是存储指向Int或Char的指针。因此MyUnion2可能占用更少的内存,并且将严格而不是懒惰

另外,我应该强调C中的“char”是一个单符号字节,而Haskell中的“char”是一个完整的unicode代码点(值0到1114111)。要在Haskell中存储一个C“字符,您需要使用

您在C中使用了联合,需要对其进行序列化和反序列化?您是否已经使用了C中的二进制格式?如果您需要发明二进制格式,那么您确实需要设计一个标记以使Haskell满意。您的C示例无法判断值是否是“构造的”使用int或char,而Haskell中的MyUnion可以判断值是由I还是C构造的


您编写的C类型也是非常危险的,就像我写入单字节“char”并读取多字节“int”一样,“int”中的其余字节可能未定义。

Yo可以轻松获得指向指针的指针(我使用类似于将
(void*)&val
参数传递到C库的方法)。关于ghci:

> a <- malloc :: (IO (Ptr Int))
> dir_a <- malloc :: (IO (Ptr (Ptr Int)))
> poke dir_a a
> poke a 5

> b <- peek dir_a
> peek b
5
>a dir\u a poke dir\u a
>捅5刀
>偷看
5.
int**是指向a的指针(指向int的指针)。在Haskell中,这是“Ptr(Ptr Int)”。