如何在一个类型类实例匹配刚性类型?
题
我想我会尝试造型上不同维度的向量数量一定数值积分,并推断该类型的类是要走的路。我需要的东西由乘法器来定义两个值和缩放它之间的差(以获得衍生物),以及能够采取的距离函数。
到目前为止,我有:
class Integratable a where
difference :: a -> a -> a
scale :: Num b => a -> b -> a
distance :: Num b => a -> a -> b
data Num a => Vector a = Vector1D a | Vector2D a a
instance Num a => Integratable (Vector a) where
difference (Vector1D x1) (Vector1D x2) = Vector1D (x1 - x2)
scale (Vector1D x) m = Vector1D (x * m)
distance (Vector1D x1) (Vector1D x2) = x1 - x2
difference (Vector2D x1 y1) (Vector2D x2 y2) = Vector2D (x1 - x2) (y1 - y2)
scale (Vector2D x y) m = Vector2D (x * m) (y * m)
distance (Vector2D x1 y1) (Vector2D x2 y2) = sqrt((x1-x2)*(x1-x2)
+ (y1-y2)*(y1-y2))
不幸的是一对夫妇在这里的问题,我还没有想出如何解决。首先,scale
函数给出错误。 GHC也说不清,因为刚性类型限制m
在一个情况下,在实例因为x
和Num
是兼容的,而在其他情况下,Vector
型......有没有一种方法来指定x
和m
是相同类型?
(我知道其实即使x
和m
都是Num
,他们可能不是的相同的Num
,我怎么可以指定这个吗?如果我不能Num
弄明白,使用Double
将被罚款,但我宁愿保持它一般。)
有一个类似的问题distance
。试图指定的返回类型Num
失败,因为它不能在a
是要含有与b
兼容值的实例定义出来。
解决方案
编辑:现在看来,我认为在函数依赖的文章从HaskellWiki提供了我能找到的最好形式的关键信息,所以我代替我的回答是,这里建议阅读。我不删除内容的其余部分,不过,因为它清楚(我希望)为什么文件描述符是有用的在这里。
除了定义问题的分组该戴夫指出...
(我知道其实即使
x
和m
都是Num
,他们可能不是的相同的Num
,我怎么可以指定这个吗?如果我不能Num
弄明白,使用Double
将被罚款,但我宁愿保持它一般。)
这是主要的问题,实际上。你不能用Integer
乘的Float
,说。在效果上,你需要的x
和规模m
是相同类型的。
另外,一个类似的问题随着距离出现时,与附加的并发症,sqrt
需要Floating
参数。所以我想你需要提过那个地方。 (最有可能的情况下,我想)。
编辑:确定,因为sqrt
只适用于Floating
值,你可以滚类型类为那些上溯造型Float
s到Double
s需要时
另一个想法涉及具有类型类Scalable
:
data Vector a = Vector1D a | Vector2D a a deriving (Show)
class Scalable a b | a -> b where
scale :: a -> b -> a
instance (Num a) => Scalable (Vector a) a where
scale (Vector1D x) m = (Vector1D (x * m))
scale (Vector2D x y) m = (Vector2D (x * m) (y * m))
此使用在Scalable
定义一个所谓的功能依赖性。事实上,试图记住的语法,我发现此链接 ...所以我想你应该是有帮助的无视我不如尝试和读取品质的信息在那里。 ; - )
我想你应该可以用这个来解决原来的问题。
其他提示
要解决的第二个错误,我认为你需要重新排序实例声明的定义。第一有两个方程difference
,则方程scale
,则两个对distance
。