如何解决带有矢量的Haskell编码中的此错误

时间:2018-10-12 16:20:25

标签: haskell

newtype Vector2 a = Vector2 (a,a)
   deriving (Show,Eq)

instance VectorSpace Vector2 where 
  vecMagnitude (Vector2 (a,b)) = (a**2 + b**2)**(1/2)

vecF :: (Floating a, VectorSpace v) => v a -> [v a] -> [a]
vecF Vector2 (a,b) ys = [ vecMagnitude ( Vector2 (a+(-1)*a'),(b+(-1)*b') ) |(a',b') <- ys ]

所以上面的编码我有错误,是vecF函数,请参见以下错误msg:

Couldn't match type ‘v’ with ‘(,) a0’
  ‘v’ is a rigid type variable bound by
    the type signature for:
      vecF :: forall a (v :: * -> *).
              (Floating a, VectorSpace v) =>
              v a -> [v a] -> [a]
    at Assign_2_EC_test.hs:74:1-58
  Expected type: v a
    Actual type: (a0, a)

In the pattern: (a, b)
  In an equation for ‘vecF’:
      vecF (a, b) ys
        = [vecMagnitude ((a + (- 1) * a'), (b + (- 1) * b')) |
             (a', b') <- ys]
Relevant bindings include
    vecF :: v a -> [v a] -> [a]

任何主意是什么错误

1 个答案:

答案 0 :(得分:4)

这里基本上存在四个问题:两个可以轻松解决,其他则需要更改签名或实现额外的功能:

  1. 您忘记在函数的开头写括号:

    vecF (Vector2 (a,b)) ys = ...
  2. 列表理解中“ yield”部分的方括号没有构成元组的方括号:

    [ vecMagnitude (Vector2 (a+(-1)*a', b+(-1)*b')) | ... ]
  3. 在您的签名中,允许第一个参数为v a类型为vVectorSpace类型为a的任何Floating,因此,您不能只添加如下构造函数:

    vecF (Vector2 (a, b)) = ...
  4. (无法直接解决),因为ysv a的列表,所以不能仅从ys枚举为:

    [ ... | (a', b') <- ys ]

最后两个问题不能轻易解决,我们可以专门化签名以使其起作用,例如:

vecF :: Floating a => Vector2 a -> [(a, a)] -> [a]
vecF (Vector2 (a,b)) ys = [ vecMagnitude ( Vector2 (a-a',b-b')) |(a',b') <- ys ]

但是我们当然可以灵活地松动以使用其他VectorSpace,例如,另一种选择是将vecF移至class定义并在{{1}中实现}子句。最后,另一个选择可能是提供额外的功能,这样您就不需要模式匹配来计算instance,例如,您可以实现一个功能:

vecMaginute

然后您可以将其实现为:

class VectorSpace v where
    -- ...
    vecDiff :: Num a => v a -> v a -> v a