无法推断(Eq a),将Eq添加到类型类

时间:2013-03-19 04:50:44

标签: haskell

我对Haskell很陌生,在尝试编译Frag时遇到了这个错误。

src/AFRPVectorSpace.hs:51:25:
    Could not deduce (Eq a) arising from a use of `/='
    from the context (VectorSpace v a)
      bound by the class declaration for `VectorSpace'
      at src/AFRPVectorSpace.hs:(32,1)-(53,23)
    Possible fix:
      add (Eq a) to the context of
        the class declaration for `VectorSpace'
    In the expression: nv /= 0
    In the expression:
      if nv /= 0 then v ^/ nv else error "normalize: zero vector"
    In an equation for `normalize':
        normalize v
          = if nv /= 0 then v ^/ nv else error "normalize: zero vector"
          where
              nv = norm v

相关代码:

class Floating a => VectorSpace v a | v -> a where
    zeroVector   :: v
    (*^)         :: a -> v -> v
    (^/)         :: v -> a -> v
    negateVector :: v -> v
    (^+^)        :: v -> v -> v
    (^-^)        :: v -> v -> v
    dot          :: v -> v -> a
    norm     :: v -> a
    normalize    :: v -> v

    v ^/ a = (1/a) *^ v

    negateVector v = (-1) *^ v

    v1 ^-^ _ = v1 ^+^ v1 -- (negateVector v2)

    norm v = sqrt (v `dot` v)

    normalize v = if nv /= 0 then v ^/ nv else error "normalize: zero vector"
        where
        nv = norm v

我的第一个猜测是我需要添加Deriving Eq或类似的东西,但我不确定我到底需要做什么。

3 个答案:

答案 0 :(得分:6)

如果您想在默认实施中使用class (Eq a,Floating a) => VectorSpace v a | v -> a /=,我猜您需要a

第二种方法是从类中删除normalize,并将其改为普通函数。

第三种方法是将约束添加到normalize的类型,使其成为Eq a => v -> v

答案 1 :(得分:5)

在ghc 7.4.1之前,Num a类有Eq a个约束,因此任何Num a也有Eq aFloating a有一个约束Num a,因此任何Floating a也都是Eq a

但是,这改变了7.4.1,其中Eq a约束(以及Show a约束)已从Num类中删除。这就是代码不再起作用的原因。

因此问题的解决方案正是aleator给出的:明确地将Eq a约束添加到VectorSpace类。

或者,您可能想要下载旧版本的ghc(例如,基于维基说明的6.8)。该版本应该编译程序而不做任何更改。然后,如果您愿意,可以更新代码以使其与更新版本的ghc一起使用。

答案 2 :(得分:1)

这不是你问题的答案(已经回答了),但由于将代码块粘贴到评论中并不容易,我会将其添加为“答案”。

您可能更喜欢使用类型系列而不是功能依赖项。类型系列允许您使用功能依赖项执行所有操作,还可以执行更多操作。这是使用类型族编写代码的一种方法。它看起来与原始代码非常相似,只是您的类型变量a已被“em”类型函数的“调用”替换为 Metric v(我能想到的最佳名称)随便。)

{-# LANGUAGE TypeFamilies, FlexibleContexts #-}

class Floating (Metric v) => VectorSpace v where
    type Metric v
    zeroVector   :: v
    (*^)         :: Metric v -> v -> v
    (^/)         :: v -> Metric v -> v
    negateVector :: v -> v
    (^+^)        :: v -> v -> v
    (^-^)        :: v -> v -> v
    dot          :: v -> v -> Metric v
    norm     :: v -> Metric v
    normalize    :: Eq (Metric v) => v -> v

    v ^/ a = (1/a) *^ v

    negateVector v = (-1) *^ v

    v1 ^-^ _ = v1 ^+^ v1 -- (negateVector v2)

    norm v = sqrt (v `dot` v)

    normalize v = if nv /= 0 then v ^/ nv else error "normalize: zero vector"
        where
        nv = norm v

以下是一些有用的链接: