1
votes

Afraid that I've grossly misunderstood types in Haskell. I'll get into it. Say I have a type defined so:

type Vector = [Num a]

So I'm using a typeclass in the definition of the synonym. Then if I want to add it to another typeclass, say Eq, maybe I would do something like so:

instance Eq Vector a where
  [] == [] = True
  [_]== [] = False
  [] == [_] = False
  (a : u) == (b : v) = (a == b) && (u == v)

But when I do this, GHC gives a

parse error on input '['

It's referring to the first left bracket in the line [_]== [] = False.

Is this caused by an issue with my type definition?

1
Do you have a typo or something missing from what you copied into the question? I don't believe you have a type Vector = [Num a] because the type variable a doesn't exist. If you did, what is the Num type? It can't be the Num class from base, since that's a constraint, not a type.Cirdec
If Vector a is a type snonymn defined as being a list [F a] why are you trying to write an Eq instance for it? There's already an Eq instance for Eq a => Eq [a].Cirdec
@AndreyChernyakhovskiy My 7.10 GHCi objects to type Vector a = [Num a] with the error Expected kind '*', but 'Num a' has kind 'Constraint', unsurprisingly even with PolyKinds and DataKinds enabled.Cirdec
@Cirdec, Mine is 7.6.3. Looks like a bug that's been fixed.ach
Btw, If I remember correctly, one cannot define an instance of type class on a type synonym.ach

1 Answers

1
votes

There are several issues with this code, preventing it from being compiled. I think you mean that Vector is parameterized by the type a that it contains:

type Vector a = [a]

I've dropped the Num constraint because it isn't needed for the rest of the example; I'll pick it up at the end.

There's already an Eq instance for lists, so this is a bit of a dead end. One way forward is to switch to a newtype:

newtype Vector a = Vector [a]

Unlike a type synonym declared with type, Haskell sees a newtype as a completely different type. A Vector is not a list, so we can define whatever type class instances we want.

Our Eq instance gets a little longer, because we have to write the Vector constructor each time. I added parentheses around Vector a in the first line.

The only other change we need to make is adding the Eq a constraint before the instance. In the last line of the definition, we compare the first element of the two Vectors. This only makes sense if the type a is an instance of Eq.

instance Eq a => Eq (Vector a) where
  Vector [] == Vector [] = True
  Vector [_] == Vector [] = False
  Vector [] == Vector [_] = False
  Vector (a : u) == Vector (b : v) = (a == b) && (Vector u == Vector v)

This compiles. You could add a Num constraint, insisting that no one may construct a Vector a unless a is Num, or that Vector a is only Eq if a is Num. If this is something you want to do, I can add an example.