标题可能不合适,请继续阅读.
我最初想要的是以下内容:我正在编写2D矢量数据
data Vect a = Vect a a deriving (Show)
Run Code Online (Sandbox Code Playgroud)
并且想要编写一个norm :: Vect a -> Double适用于所有Vect aa Integral或其实例的函数Floating.
对于Double,我可以写道:
norm :: Vect Double -> Double
norm (Vect x y) = sqrt $ x^2 + y^2
Run Code Online (Sandbox Code Playgroud)
但我希望这个功能也适用Vect Int.我可以写另一个函数,如:
normFromInt :: (Integral a) => Vect a -> Double
normFromInt (Vect x y) = sqrt . fromIntegral $ x^2 + y^2
Run Code Online (Sandbox Code Playgroud)
有两个功能似乎相当尴尬.实现这一目标的好方法是什么?
我尝试使用特殊类:
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
Run Code Online (Sandbox Code Playgroud)
但有了这个,当usnig`norm(Vect 3.0 4.0 :: Vect Double)我得到一个错误
Overlapping instances for Vectorlike (Vect Double)
|| print $ norm (Vect 3.0 4.0 :: Vect Double)
foo.hs|40 col 13 error| Overlapping instances for Vectorlike (Vect Double)
|| arising from a use of `norm'
|| Matching instances:
|| instance Integral a => Vectorlike (Vect a)
|| -- Defined at /home/yosh/foo.hs:26:10
|| instance Vectorlike (Vect Double)
|| -- Defined at /home/yosh/foo.hs:32:10
Run Code Online (Sandbox Code Playgroud)
我的问题是我如何定义norm以便它适用于整数和浮动,并且错误消息不是主要关注点(这对我来说很令人费解,但我想我之后可以使用它).
您只需要使用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
Run Code Online (Sandbox Code Playgroud)
那么它也适用于更多类型而不仅仅是Double.
至于错误消息,从技术上讲,这两个实例上没有重叠,但你绝对可以.有人可以定义一个Integral Double实例,然后导入你的代码.突然,编译器无法决定使用哪个实例!
虽然这种精确的情况不太可能发生,但类型系统确实允许某人为实例Integral进行实例化Double,而这肯定会出现在其他类型类和数据类型中.
| 归档时间: |
|
| 查看次数: |
76 次 |
| 最近记录: |