多态与类型变量?

时间:2015-05-12 02:27:57

标签: haskell

标题可能不合适,请继续阅读。

我最初想要的是以下内容:我正在编写2D矢量数据

{card:label=mycard}    
{table-plus:columnAttributes=style=width:300px, style=width:300px}
||Head1|D1|

||Head2|D2|
{table-plus}
{card}

并希望编写适用于所有data Vect a = Vect a a deriving (Show) 的{​​{1}}函数,其中a是norm :: Vect a -> DoubleVect a的实例。

对于Double,我可以写道:

Integral

但是我希望这个功能也适用于Floating。我可以编写另一个函数,如:

norm :: Vect Double -> Double
norm (Vect x y) = sqrt  $ x^2 + y^2

有两个功能似乎相当尴尬。实现这一目标的好方法是什么?

我尝试使用特殊类:

Vect Int

但有了这个,当usnig`norm(Vect 3.0 4.0 :: Vect Double)我收到错误

normFromInt :: (Integral a) => Vect a -> Double
normFromInt (Vect x y) = sqrt . fromIntegral $ x^2 + y^2

我的问题是我如何定义class Vectorlike a where norm :: a -> Double instance (Integral a) => Vectorlike (Vect a) where norm (Vect x y) = sqrt . fromIntegral $ x^2 + y^2 -- | -- >>> norm (Vect 3 4 :: Vect Int) -- 5.0 instance Vectorlike (Vect Double) where norm (Vect x y) = sqrt $ x^2 + y^2 以便它适用于整数和浮动,并且错误信息不是主要关注点(它让我感到困惑,但我认为我可以使用之后)。

1 个答案:

答案 0 :(得分:6)

您只需使用realToFrac即可将Real r => r值转换为Fractional f => f值:

norm :: (Real r, Floating f) => Vect r -> f
norm (Vect x y) = sqrt . realToFrac $ x^2 + y^2

然后它也适用于更多类型,而不仅仅是Double

对于错误消息,从技术上讲,这两个实例没有重叠,但你绝对可以。有人可以定义Integral Double实例,然后导入您的代码。突然,编译器无法决定使用哪个实例!

虽然不太可能发生这种精确的情况,但是类型系统确实允许某人为Integral实例Double,这肯定会出现在其他类型类和数据类型中。