我有一个数据类型
newtype Zq q = Zq (IntType q)
其中“q”将是该类的一个实例
class Foo a where
type IntType a
'IntType' 只是与 'q' 关联的底层表示(即 Int、Integral 等)。
我想让 Zq 成为一个实例数据.矢量.拆箱 http://hackage.haskell.org/packages/archive/vector/0.9.1/doc/html/Data-Vector-Unboxed.html。我们目前正在使用大约 50 行简单代码手动派生 Unbox,如上面链接中建议的那样。我们将在代码中创建几种不同的类型“Unbox”,因此为每种类型编写 50 行并不吸引人。
我找到了两个替代方案here http://comments.gmane.org/gmane.comp.lang.haskell.libraries/17252。一种替代方法是使用这个包 http://hackage.haskell.org/packages/archive/vector-th-unbox/0.1.0.0/doc/html/Data-Vector-Unboxed-Deriving.html它使用 Template Haskell 派生 Unbox 的实例。 TH 代码如下所示:
derivingUnbox "Zq"
[d| instance (Foo q, U.Unbox (IntType q)) => Unbox' (ZqBasic q) (IntType q) |]
[| \ (Zq x) -> x |]
[| \ x -> Zq x |]
问题是,我无法使用关联类型同义词定义实例 http://www.haskell.org/pipermail/glasgow-haskell-users/2008-October/015794.html(或者我可以吗?)
[一个相关问题:为什么类型同义词实例 http://hackage.haskell.org/trac/haskell-prime/wiki/TypeSynonymInstances,FlexibleInstances 隐含的扩展,不允许联系输入同义词实例?这是从根本上来说是一种不同的野兽吗?]
我目前对该问题的解决方案是将 Zq 重新定义为
newtype Zq q i = Zq i
然后添加等式约束
i~(IntType q)
在涉及 (Zq q i) 的每个实例中,这不是很优雅。我的(工作)拆箱推导变成
derivingUnbox "Zq"
[d| instance (U.Unbox i, i~IntType q, Foo q) => Unbox' (Zq q i) i |]
[| \ (Zq x) -> x |]
[| \ x -> Zq x |]
我觉得我应该能够在不显式暴露类型“i”的情况下完成此任务。我所做的只是将其从关联的类型同义词移至具有相等约束的显式参数。为什么这“从根本上”是一种不同的(而且显然更安全的)方法?有什么方法可以避免添加类型参数“i”并仍然获得自动拆箱派生?
除了额外的类型参数之外,我在使用 TH 包来派生 Unbox for (Vector r) 时遇到了麻烦,也就是说,我想制作 Unbox Vectors 的 Unbox Vector。我的尝试是这样的:
newtype Bar r = Bar (Vector r)
derivingUnbox "Bar"
[d| instance (Unbox r) => Unbox' (Bar r) (Vector r) |]
[| \ (Bar x) -> x |]
[| \ x -> Bar x |]
但我收到(很多)错误,例如:
`basicUnsafeFreeze` is not a (visible) method of class `Data.Vector.Generic.Base.Vector`
我不知道为什么它找不到这个方法,而它对于我的 Zq 类型来说效果很好。
列出的第二种方法above http://comments.gmane.org/gmane.comp.lang.haskell.libraries/17252正在使用扩展 GeneralizedNewtypeDeriving。我发现这种方法的最大问题是我有一些需要拆箱的实际数据(而不是 Newtype)。但是,仅使用扩展名,我应该能够编写
newtype Zq q = Zq (IntType q) deriving (Unbox, M.MVector MVector, G.Vector Vector)
或者至少
newtype Zq q i = Zq i deriving (Unbox, M.MVector MVector, G.Vector Vector)
第一个导致错误:
No instance for (Unbox (IntType q)) arising from the `deriving` clause of a data type declaration
No instance for (M.MVector MVector (IntType q)) ""
No instance for (G.Vector Vector (IntType q)) ""
第二个给出:
No instance for (M.MVector MVector i) ""
No instance for (G.Vector U.Vector i) ""
我不确定为什么它不能导出这些实例,因为上面的帖子让我相信它应该能够导出这些实例。也许我可以摆脱使用与 GeneralizedNewtypeDeriving 相关的类型同义词? (当我需要派生“数据”的 Unbox 时,这仍然(可能)不能解决我的问题。)
感谢您的帮助!