Haskell - need to define Vector2 instance for typeclass

≡放荡痞女 提交于 2020-01-22 04:11:47

问题


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

class VectorSpace v where
     vZero :: (Num a) => v a
     vSum :: (Num a) => v a -> v a -> v a
     vScalarProd :: (Num a) => a -> v a -> v a
     vMagnitude :: (Floating a) => v a -> a

Need to define for Vector2 to be instances of the type class VectorSpace.


回答1:


So here is what I tried so far:

instance VectorSpace (a,a) => VectorSpace Vector2 a
  vecZero = (0.0,0.0)
  vecSum (x,y) (x',y') = (x+x',y+y')

The first problem here is syntax. You need a where at the end of the first line, and if Vector2 a is supposed to be the instance head then it needs to go in parentheses:

instance VectorSpace (a,a) => VectorSpace (Vector2 a) where

That, however, doesn't match the kinds of your declared class.

class VectorSpace (v :: * -> *) where
    vZero :: (Num a) => v a
    ...

i.e., the class already has the assumption built in that v will be applied to some a parameter. Thus the instance head should not contain that parameter, it should just look like

instance (...?) => VectorSpace Vector2 where

In fact it turns out you don't need any constraints at all here.

instance VectorSpace Vector2 where

Now as for the methods,

  vecSum (x,y) (x',y') = (x+x',y+y')

that would be a perfectly sensible implementation if your type were the tuple type. However your type is actually a newtype wrapped tuple, and newtypes always need explicit constructors. Like

  vecSum (Vector2 (x,y)) (Vector2 (x',y')) = Vector2 (x+x',y+y')

This is a bit silly really: you have both a named constructor and a tuple constructor, nested. It's also pretty inefficient since tuples incur extra indirection (laziness, cache). The type should better be defined as

data Vector2 a = Vector2 !a !a

where, because the fields are strict, GHC can unbox the numbers. In that case, the definition would be

  vecSum (Vector2 x y) (Vector2 x' y') = Vector2 (x+x') (y+y')

Mind, as I've already commented it is IMO not good for a vector space class to parameterise v a at all. In the vector-space library, the instances aren't required to be parameterised; one of the advantages is that you can directly give an instance for ordinary tuples without needing any newtype wrapping.



来源:https://stackoverflow.com/questions/52778291/haskell-need-to-define-vector2-instance-for-typeclass

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!