首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法推导(Eq a),正在将Eq添加到类型类

无法推导(Eq a),正在将Eq添加到类型类
EN

Stack Overflow用户
提问于 2013-03-19 12:50:44
回答 3查看 548关注 0票数 4

我是Haskell的新手,在尝试编译Frag时遇到了这个错误。

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

相关代码:

代码语言:javascript
复制
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或类似的东西,但我不确定我到底需要做什么。

EN

回答 3

Stack Overflow用户

发布于 2013-03-19 13:55:02

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

第二种选择是从类中删除normalize,使其成为一个普通函数。

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

票数 6
EN

Stack Overflow用户

发布于 2013-03-19 15:24:42

在GHC7.4.1之前,Num a类有Eq a约束,所以任何Num a也有Eq aFloating a有一个约束Num a,因此任何Floating a也是Eq a

然而,这在7.4.1中发生了变化,从Num类中删除了Eq a约束(以及Show a约束)。这就是代码不再工作的原因。

因此,这个问题的解决方案正是aleator给出的:显式地向VectorSpace类添加Eq a约束。

或者,你可能想要下载一个旧版本的ghc (例如基于维基笔记的6.8版)。该版本应该在没有任何更改的情况下编译程序。然后,如果您愿意,可以更新代码以使其与较新版本的ghc一起工作。

票数 5
EN

Stack Overflow用户

发布于 2013-03-19 19:33:32

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

您可能更喜欢使用类型族,而不是函数依赖项。类型族允许你对函数依赖做任何你能做的事情,还有更多。这里有一种使用类型族编写代码的方法。它看起来与您的原始代码非常相似,只是您的类型变量a已被替换为对类型函数Metric v的“调用”(这是我能想到的最好的名称)。

代码语言:javascript
复制
{-# 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

以下是一些有用的链接:

  • http://www.haskell.org/haskellwiki/GHC/Type_families
  • http://nattermorphisms.blogspot.ie/2008/10/2-minute-intro-to-associated-types-type.html
  • http://www.haskell.org/pipermail/haskell-cafe/2009-February/055890.html
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15491707

复制
相关文章

相似问题

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