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)
-}
我无法实现上述正常功能。怎么能让它通过类型检查?
答案 0 :(得分:4)
三个选项:
更改您的类型签名:
normal :: (Integral a, Floating b) => V2 a -> V2 b
然后指定一个函数将(Integral a) => V2 a
转换为(Floating b) => V2 b
并将其应用于v
之前的*$
。
将Floating
结果从1 / len v
转换为Integral
值(round
等)。
按照Landei的建议并强制在任何地方使用Floating
。
len
接收(Integral a) => V2 a
并返回(Floating b) => b
。然后,您对结果执行1 /
,结果仍为(Floating b) => b
类型。从您的*$
类型开始,它需要V2 a
和a
,但在这种情况下,您的v :: (Integral a) => V2 a
和(1 / len v) :: (Floating b) => b
不是等效类型。
所以你必须在某个地方做某种形式的强制。
答案 1 :(得分:1)
最小修复只是更改普通的类型签名:
normal :: Floating a => V2 a -> V2 a
以下是类型:
sqrt :: Floating a => a -> a
所以len没有理由接受Floating
以外的其他内容。
答案 2 :(得分:0)
怎么样......
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。
答案 3 :(得分:-1)
找到它。当len
返回浮动时,需要在normal
中浮动。除此以外
你可以尝试定义
($*) :: Num a, ?b => V2 a -> b -> V2 a
Anyay
normal :: (Num a, Integral a, Floating a) => V2 a -> V2 a
作品
您也可以将len定义更改为
len ::(Num a)=> V2a - >一个