data V2 a = V2 a a deriving (Show, Eq)
instance Num a => Num (V2 a) where
(-) (V2 x0 y0) (V2 x1 y1) = V2 (x0 - x1) (y0 - y1)
(+) (V2 x0 y0) (V2 x1 y1) = V2 (x0 + x1) (y0 + y1)
(*) (V2 x0 y0) (V2 x1 y1) = V2 (x0 * x1) (y0 * y1)
abs = undefined
signum = undefined
fromInteger = undefined
instance Fractional a => Fractional (V2 a) where
(/) (V2 x0 y0) (V2 x1 y1) = V2 (x0 / x1) (y0 / y1)
recip = undefined
fromRational = undefined
-- Multiply by scalar
(*$) :: Num a => V2 a -> a -> V2 a
(*$) (V2 x y) s = V2 (x * s) (y * s)
-- Length of the vector
len :: (Num a, Integral a, Floating b) => V2 a -> b
len (V2 x y) = sqrt $ fromIntegral $ x * x + y * y
normal :: (Num a, Integral a) => V2 a -> V2 a
normal v = v *$ (1 / len v)
{-
Math\V2.hs:31:20:
Could not deduce (Fractional a) arising from a use of `/'
from the context (Num a, Integral a)
bound by the type signature for
normal :: (Num a, Integral a) => V2 a -> V2 a
at Math\V2.hs:31:1-27
Possible fix:
add (Fractional a) to the context of
the type signature for
normal :: (Num a, Integral a) => V2 a -> V2 a
In the second argument of `(*$)', namely `(1 / len v)'
In the expression: v *$ (1 / len v)
In an equation for `normal': normal v = v *$ (1 / len v)
Math\V2.hs:31:22:
Could not deduce (Floating a) arising from a use of `len'
from the context (Num a, Integral a)
bound by the type signature for
normal :: (Num a, Integral a) => V2 a -> V2 a
at Math\V2.hs:31:1-27
Possible fix:
add (Floating a) to the context of
the type signature for
normal :: (Num a, Integral a) => V2 a -> V2 a
In the second argument of `(/)', namely `len v'
In the second argument of `(*$)', namely `(1 / len v)'
In the expression: v *$ (1 / len v)
-}我在实现上面的普通函数时遇到了问题。怎样才能让它通过类型检查?
发布于 2011-11-09 18:19:43
三个选项:
=> ::(整型a,浮点型b) V2 a -> V2 b
然后指定一个函数将(Integral a) => V2 a转换为(Floating b) => V2 b,并在v将Floating结果从1 / len v转换为Integral值(round等)之前将其应用于。
Floating。len接受一个(Integral a) => V2 a并返回一个(Floating b) => b。然后对仍为(Floating b) => b类型的结果执行1 /。从您的*$类型中,它需要一个V2 a和一个a,但在本例中,您有v :: (Integral a) => V2 a和(1 / len v) :: (Floating b) => b,它们不是等价类型。
所以你必须在某个地方进行某种形式的胁迫。
发布于 2011-11-09 18:21:24
最小的修复方法是将类型签名更改为normal:
normal :: Floating a => V2 a -> V2 a以下是这些类型:
sqrt :: Floating a => a -> a因此,len没有理由接受Floating之外的其他内容。
发布于 2011-11-09 18:16:04
不如..。
len :: (Floating a) => V2 a -> a
len (V2 x y) = sqrt $ x * x + y * y
normal :: (Floating a) => V2 a -> V2 a
normal v = v *$ (1.0 / len v)当然,这意味着你需要在计算法线之前转换一个V2 Int,但这就像你必须在除法之前转换一个Int一样。
https://stackoverflow.com/questions/8063255
复制相似问题