[Haskell-cafe] Re: Fundeps: I feel dumb

oleg at pobox.com oleg at pobox.com
Wed Apr 12 23:27:03 EDT 2006

Creighton Hogg wrote:

>     No instance for (MatrixProduct a (Vec b) c)
>       arising from use of `<*>' at <interactive>:1:3-5
>     Probable fix: add an instance declaration for (MatrixProduct a
>     (Vec b) c)
>     In the definition of `it': it = 10 <*> (vector 10 ([0 .. 9]))

Let us look at the instance

  class MatrixProduct a b c | a b -> c where
    (<*>) :: a -> b -> c
  instance (Num a) => MatrixProduct a (Vec a) (Vec a) where

it defines what happens when multiplying a vector of some numeric type
'a' by a value _of the same_ type. Let us now look at the error
>	(MatrixProduct a (Vec b) c)

That is, when trying to compile your expression
	10 <*> (vector 10 ([0 .. 9]))
the typechecker went looking for (MatrixProduct a (Vec b) c)
where the value and the vector have different numeric types. There is
no instance for such a general case, hence the error. It is important
to remember that the typechecker first infers the most general type
for an expression, and then tries to resolve the constraints. In your
	10 <*> (vector 10 ([0 .. 9]))
we see constants 10, 10, 0, 9. Each constant has the type Num a => a.
Within the expression 0 .. 9, both 0 and 9 must be of the same type
(because [n .. m] is an abbreviation for enumFromThen n m, and
to the type of the latter
	  enumFromThen :: a -> a -> [a]
both arguments must be of the same type).

But there is nothing that says that the first occurrence of 10 must be
of the same numeric type as the occurrence of 9. So, the most general
type assignment will be (Num a => a) for 10, and (Num b => b) for 9.

Solution: either choose a specific (non-polymorphic type)

> test1 = (10::Int) <*> (vector 10 [0..9::Int])

Or tell the typechecker that those constants must be of the same type:

> test2 = let n = 10 in n <*> (vector 10 [0..(9 `asTypeOf` n)])

More information about the Haskell-Cafe mailing list