2

我想我会尝试对不同维度的向量进行一些数值积分建模,并认为类型类是要走的路。我需要一些东西来定义两个值之间的差异并通过乘数对其进行缩放(以获得导数),以及能够采用距离函数。

到目前为止,我有:

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了严格的类型限制,在另一种情况下在类型中给出......有没有办法指定它并且是相同的类型?NumVectorxm

(事实上​​,我意识到即使xm都是Num,它们也可能不一样 Num。我该如何指定这个?如果我无法用 来弄清楚Num,使用Double会很好,但我宁愿保持一般性。)

有一个类似的问题distance。尝试指定返回类型Num失败,因为它无法在实例定义中说明a将包含与b.

4

2 回答 2

1

编辑:在我看来,HaskellWiki 中关于功能依赖的文章以我能找到的最佳形式提供了关键信息,所以我建议阅读它而不是我的答案。不过,我不会删除其余的内容,因为它清楚(我希望)为什么 FD 在这里有用。


除了戴夫指出的定义分组问题...

(事实上​​,我意识到即使xm都是Num,它们也可能不一样 Num。我该如何指定这个?如果我无法用 来弄清楚Num,使用Double会很好,但我宁愿保持一般性。)

这实际上是主要问题。比如说,你不能将 a 乘以Integera 。Float实际上,您需要xmin 比例是相同的类型。

此外,距离也会出现类似的问题,还有sqrt需要Floating争论的额外并发症。所以我想你也需要在某个地方提到这一点。(我猜最有可能在实例上)。

编辑:好的,由于sqrt仅适用于值,因此您可以为那些在需要时将 s 向上转换为sFloating的类型滚动。FloatDouble

另一个想法涉及拥有一个 typeclass 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。事实上,为了记住它的语法,我找到了这个链接......所以我想你应该忽略我提供帮助的低劣尝试并阅读那里的质量信息。;-)

我认为您应该能够使用它来解决您原来的问题。

于 2009-12-22T15:44:41.573 回答
0

要修复第二个错误,我认为您需要在实例声明中重新排序定义。首先有 的两个方程difference,然后是 的方程scale,然后是 的两个方程distance

于 2009-12-22T15:28:56.253 回答