2017-10-17 106 views
2

我已经一个Haskell模块中的以下数据类型和我想写可储存instace经由FFI与C使用它:如何为递归类型创建一个Storable实例?

data MyType a = 
     TypeDouble Double 
     | TypeLst [a] 
     | TypeAdd (MyType a) (MyType a) 

我开始通过定义sizeOf功能:

instance Storable a => Storable (MyType a) where 
    sizeOf (TypeDouble _) = sizeOf (0 :: Double) 
    sizeOf (TypeLst lst) = sum $ map sizeOf lst 
    sizeOf (TypeAdd a b) = sizeOf a + sizeOf b 

它编译得很好,但我不知道如何实现peekpoke函数。我认为这些功能的实现方式与this answer中的相同,但只有当列表中的所有元素具有相同的大小时,此实现才有效。

什么是实施peekpoke功能递归类型的正确方法,其中元素具有浮动大小?

+3

也许你应该首先定义你期望用作Haskell'MyType a'的对应物的C类型。你的'sizeOf'似乎对我有点乐观。你的C类型可能需要一个int/enum /任何标签,这有助于区分三种Haskell构造函数;该标签的大小应添加到所有尺寸。 – chi

+1

值得注意的是,由于历史原因,“sizeOf”具有错误的签名。它实际上应该是['Tagged a Int'](http://hackage.haskell.org/package/tagged-0.8.5/docs/Data-Tagged.html#t:Tagged)(或'proxy a - > Int ')而不是'a - > Int'。这将清楚地表明,这实际上不能取决于各个值_,但对于给定类型的_all_值应该是相同的。 ([文档](http://hackage.haskell.org/package/base-4.10.0.0/docs/Foreign-Storable.html#v:sizeOf)确实会这么说)。 – leftaroundabout

+0

@leftaroundabout即使签名是现在是历史。通过'TypeApplications'和'AllowAmbigousTypes',它应该* sizeOf :: Storable a => Int',可以通过'sizeOf @ a'使用。 – HTNW

回答

7

对此,您不能有Storable。这些数据类型需要具有固定大小,就像C struct s。另外请注意,sizeof不应该检查您给它的价值。它只是type参数的代理/载体,因此您可以编写例如sizeof (undefined::Int)。也许看看Foreign.Marshal.Array

相关问题