首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >数值类型类的类型错误

数值类型类的类型错误
EN

Stack Overflow用户
提问于 2011-11-09 17:59:20
回答 4查看 1.8K关注 0票数 0
代码语言:javascript
复制
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)

-}

我在实现上面的普通函数时遇到了问题。怎样才能让它通过类型检查?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-11-09 18:19:43

三个选项:

  • 更改您的类型签名:

=> ::(整型a,浮点型b) V2 a -> V2 b

然后指定一个函数将(Integral a) => V2 a转换为(Floating b) => V2 b,并在vFloating结果从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,它们不是等价类型。

所以你必须在某个地方进行某种形式的胁迫。

票数 4
EN

Stack Overflow用户

发布于 2011-11-09 18:21:24

最小的修复方法是将类型签名更改为normal:

代码语言:javascript
复制
normal :: Floating a => V2 a -> V2 a

以下是这些类型:

代码语言:javascript
复制
sqrt :: Floating a => a -> a

因此,len没有理由接受Floating之外的其他内容。

票数 1
EN

Stack Overflow用户

发布于 2011-11-09 18:16:04

不如..。

代码语言:javascript
复制
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一样。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8063255

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档