[Haskell-cafe] Vectors in Haskell

Udo Stenzel u.stenzel at web.de
Fri Dec 23 06:12:49 EST 2005

Jeff.Harper at handheld.com wrote:
> {-
>    This code is works with Glasgow, ghci, with these options:
>   -fglasgow-exts
>   -fallow-undecidable-instances
>   -fno-monomorphism-restriction
>   -fallow-incoherent-instances
> -}

First off, try lighter weapons first.  Be switching on all possible
extensions you're also getting worse error reporting and more unexpected
interactions.  -fglasgow-exts and -fallow-overlapping-instances should
be enough.

> v1 = Vector [1,2,3]
> v2 = Vector [10,15,2]
> I'd like for .+ to work with v1 and v2.  So, I can use things like Vector
> [1,2,3] in expressions, instead of Vector[(1::Int),2,3].

And what do you think "work" would mean?  It is unknown whether v1 and
v2 contain Ints or Doubles, so it is not known how to add them.  What do
you expect the compiler to do?  Usually the result of the addition would
be known (you want a Vector Double), but with the mixed additions you
defined that doesn't imply a type for v1 or v2.

> Vector2.hs:38:12:
>     Overlapping instances for Add (Vector Int) (Vector Int) (Vector Int)
>       arising from use of `.+' at Vector2.hs:38:12-13
>     Matching instances:
>       Vector2.hs:31:0: instance (Add a b c) => Add (Vector a) (Vector b)
> (Vector c)
>       Vector2.hs:15:0: instance (Num d) => Add d d d
>     In the definition of `test1': test1 = vi1 .+ vi2
> I interpret this as saying that the compiler doesn't know if the .+ in "test1 =
> vi1 .+ vi2" should match the Vector instance or the Num instance.  I could
> understand this if Vector was an instance of class Num.  However, this is not
> the case.  I figure either Glasgow has a bug or I don't really understand the
> error message.

You don't understand the mechanism.  GHC first looks at the instance
head, then decides which instance to use, then tries to satisfy the
context.  Now try to find an instance for (Add (Vector Int) (VectorInt)
(Vector Int)):

Does it match (Add (Vector a) (Vector b) (Vector c))?  It does.
Does it match (Add d d d)?  It too does.
Which one is more specialized?  Neither.  I can't decide.

You want to express a priority.  This is possible, but not obvious.
First, define overlapping instances in such a way than one is strictly
more general:

instance (Add a b c) => Add (Vector a) (Vector b) (Vector c)
instance (...) => Add a b c -- see below

To declare (Add d d d) you need a second class:

class Add' a b c
instance Num d => Add' d d d

instance Add' a b c => Add a b c

This should work (but I didn't test it).  For three times (Vector Int),
the first instance for Add is choosen, since it is strictly more
specific than the second.  For three times Int, only the second can
match.  Then the context (Add' ...) is satisfied.  For three times
String (which must not work), the second instance for Add matches, but
the context (Add' ...) cannot be satisfied.  It works a bit like Prolog
written backwards and without backtracking :)

> I'd be grateful for any suggestions or pointers to information on how to
> implement vectors (or other mathematical types) so they seamlessly and
> intuitively work with types, classes and operators already built into Haskell.

In general, do something more simple, as Cale suggested.  The implicit
conversions don't buy you much, but the type system extensions will
cause lots of headaches.

Part of any serious QA is removing Perl code the same way you go over a
dilapidated building you inherit to remove chewing gum and duct tape and
fix whatever was kept together for real. -- Erik Naggum
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://www.haskell.org//pipermail/haskell-cafe/attachments/20051223/9ca8239d/attachment.bin

More information about the Haskell-Cafe mailing list