我目前正在使用相当不错的haskell-eigen库并偶然发现了一个基本但可能是基本的问题(我对实际的haskell开发很新)。
我使用他们的基本矩阵类型
data Matrix a b :: * -> * -> *
其中a表示haskell,b表示内部C类型。这是通过限制
实现的Elem a b
与
Elem Double CDouble
Elem Float CFloat
-- more for complex types...
虽然这不是我想问的问题,但我有点不明白为什么这样做。由于它显然是一种功能映射,我已经不明白为什么这被制定为等价关系,但无论如何...
我现在想要从Key包中定义(作为一个简单的例子 - 我有几个)keys的实例。它定义了给定容器的索引键,例如
type instance [] = Int
所以Key的实例是在类型类型上定义的* - > *
但是由于这个要求,这不起作用:
type instance Key Matrix = (Int, Int)
我必须以某种方式使Matrix变得善良* - > *。所以(来自c ++我会用traits类来做),我试过这个:
type family CType a where
CType Double = CDouble
CType Float = CFloat
type MatX a = Matrix a (CType a)
换句话说,我试图使用类型同义词作为实现上述功能类型映射的手段。
现在我尝试了以下内容:
type instance Key MatX = (Int, Int)
它给了我“类型同义词'MatX'应该有1个参数,但是没有给出”我甚至尝试了明显的错误
type instance Key (MatX a) = (Int, Int)
它给了我“期望的种类* - > *,但是MatX a有种类*”。这听起来像“我编译器期望一个类型超过0但是 - 是一个类型同义词 - 少于1个参数”。
所以我的问题是:如何通常在haskell中映射类型以解决这种类型的不匹配或以另一种方式摆脱它。
P.S。:我很清楚特征矩阵具有索引函数,但是
修改:添加了对所提及包的参考链接。
答案 0 :(得分:5)
你快到了。缺少的一个是type
个同义词必须使用饱和 - 也就是说,你必须提供它的所有参数。 MatX
本身不是有效类型,只有MatX a
。这样做的原因是type
同义词只是同义词 - 它们在编译时被扩展,这意味着编译器需要知道所有type
同义词的参数,以便在获得有效类型之后扩展
修复方法是将您的type
同义词更改为newtype
。
newtype MatX a = MatX { getMatX :: Matrix a (CType a) }
newtype
可以部分应用,因为MatX a
现在是与Matrix a (CType a)
不同的类型。
type instance Key MatX = (Int, Int)
答案 1 :(得分:4)
另一个答案显示了将类型同义词转换为可在实例声明中使用的内容的一般情况。但在这种特定情况下,它可以更简单:因为索引类型对于所有不同的矩阵是相同的,所以您可以只提供获得正确类型所需的参数。因此:
type instance Key (Matrix a) = (Int, Int)
不需要与Haskell和C类型相关的额外类型系列,不需要新类型。这也将使得使用按键'库的API更加简单,因为您不需要在每次调用时进行任何新类型换行和解包。