4

私は 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またはそのようなものを追加する必要があるということですが、正確に何をする必要があるのか​​ わかりません。

4

3 に答える 3

6

デフォルトの実装でforclass (Eq a,Floating a) => VectorSpace v a | v -> aを使用する場合は、必要があると思います。/=a

2 番目の選択肢は、クラスから削除normalizeし、代わりに通常の関数にすることです。

3 番目の方法は、制約を の型に追加してnormalize、 にすることEq a => v -> vです。

于 2013-03-19T05:55:02.400 に答える
5

ghc 7.4.1 より前では、Num aクラスにはEq a制約があったため、 anyNum aにもEq a. Floating a制約Num aがあるので何でもFloating aありでしたEq a

ただし、これは 7.4.1 で変更され、Eq a制約 (および制約) がクラスShow aから削除されました。Numこれが、コードが機能しなくなった理由です。

したがって、問題の解決策はまさに aleator が与えたものです:クラスEq aに明示的に制約を追加しますVectorSpace

別の方法として、古いバージョンの ghc をダウンロードすることもできます (例: wiki のメモに基づく 6.8)。そのバージョンは、変更なしでプログラムをコンパイルする必要があります。その後、コードを更新して、必要に応じて新しいバージョンの ghc で動作するようにすることができます。

于 2013-03-19T07:24:42.330 に答える
1

これはあなたの質問に対する回答ではありませんが (すでに回答済みです)、コードのブロックをコメントに貼り付けるのは簡単ではないため、「回答」として追加します。

機能的な依存関係ではなく、型ファミリを使用することをお勧めします。型ファミリを使用すると、関数の依存関係でできることすべてに加えて、さらに多くのことを行うことができます。型ファミリを使用してコードを記述する 1 つの方法を次に示します。型変数が型関数aへの「呼び出し」に置き換えられていることを除いて、元のコードと非常によく似ています(私がすぐに思いつく名前です)。 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

便利なリンクを次に示します。

于 2013-03-19T11:33:32.380 に答える