Christopher Jeris wrote:

> Hi everyone.  I am a sometime O'Camler just learning Haskell.  Type
> classes are fun and I like the expressiveness you get without grafting a
> whole "object system" onto your nice functional language.  But sometimes
> they baffle me, as in the following.
>
> This function fails to typecheck:
> -- Determinant algorithm from Knuth 4.6.4(31).
> -- briefly:            [x22 - (x21/x11)x12 ... x2n - (x21/x11)x1n]
> -- det x[ij] = x11 det [ ...        xij - (xi1/x11)x1j       ... ]
> --                     [xn2 - (xn1/x11)x12 ... xnn - (xn1/x11)x1n]
> det :: (Ix a, Num b) => Array (a,a) b -> b
> det x | (i0,i1) /= (j0,j1)   = error "det: square matrices only"
>       | null (range (i0,i1)) = (fromInteger 1)::b -- ERROR is here
>       | i0 == i1             = x!(i0,i0)
>       | True                 = x!(i0,i0) * det x'
>     where ((i0,j0), (i1,j1)) = bounds x
>           i'0 = (range (i0,i1)) !! 1
>           b' = ((i'0,i1), (i'0,i1))
>           x' = accum (-)
>                      (array b' [(ij, x!ij) | ij <- range b'])
>                      [((i,j), (x!(i,i0) / x!(i0,i0)) * x!(i0,j))
>                       | (i,j) <- range b']
>
> Hugs98 (May, Hugs extended mode) gives the error
> ERROR "Matrix.hs" (line ...): Cannot justify constraints in type
> annotation
> *** Expression    : fromInteger 1
> *** Type          : b
> *** Given context : ()
> *** Constraints   : Num b
>
> I wrote the offending clause as (fromInteger 1)::b because, when it was
> just (fromInteger 1), the inferred type of det had b bound equal to Num
> Double, which wasn't general enough to match my declared type.  But as the
> constraint Num b is declared in the type I want det to have, I don't
> understand why the constraint is not found during type checking.
>
> Simpler functions such as
> test :: Num a => Bool -> a
> test False = (fromInteger 0)::a
> test True = (fromInteger 1)::a
> typecheck just fine.
>
> Can you show me what I am missing?

Let's take the last question first.  The type variable `a' that you are trying to
use in `(fromInteger 0)::a' is not bound by the type signature as you seem to
believe.  The type variables in the signature scope only ofer the signature.
So you are asking for `(fromInteger 0)' to have any type, whic is of couse impossible.

Back to your original problem.  You should remove the `::b'.  You problem is that
the type you have given is too general.  You have declared the result to be Num,
but you are using `/' in the function.  You cannot divide in Num, so replace Num
by Fractional.

--

        -- Lennart





Reply via email to