Having contraints like 'Fractional Int => IO ()'

D. Tweed tweed@compsci.bristol.ac.uk
Tue, 13 Nov 2001 08:10:38 +0000 (GMT)

On Tue, 13 Nov 2001, Jesper Louis Andersen wrote:

> This problem has had my attention for a while now. I hope someone would
> like to help me out on the problem.
> I have a simple average function defined as:
> mean            :: (Fractional a) => [a] -> a
> mean l          = (sum l)/ fromIntegral (length l)
> Which imposes a type constraint (of course). My problem is, that i
> cannot ``let go'' of this constraint. The constraint travels through the
> call tree of my functions and ends at the top-level function, which is
> defined as a Monad (I need some IO operations on some files). Now, I
> have tried to solve the problem, but the closest I have got is to make
> my main function be of type:
> main		:: Fractional Int => IO ()

In principle a type constraint is discharged (I hope this is the correct 
word) in the roughly the same way as a general polymorphic type, i.e.,

f :: a -> a                         f :: Eq a => a -> a

g (x::Int) = f x                    g (x::Int) = f x

===>                                ===>
a `instantiated' here as Int        a `instantiated' here as Int
f used at type f :: Int -> Int      check:allowed as Int is instance of Eq
g has type g :: Int -> Int          f used at type f :: Int -> Int
                                    g has type g :: Int -> Int

so that at some point the somewhere higher up in the call tree the
polymorphism is `made concrete' and type class constraints are discharged
by some combination of type signature information, manual typing of
expressions with :: as above and pattern match data. (This may not be the
concrete terminology; I'm only a Haskell hobbyist.)

So it sounds like you're using polymorphic functions (and hence having
undischarged type constraints) all the way to the top of your monad, when
you really need (for the program to make sense) to reduce things to
conrete types at some point. E.g.,I can imagine you can use read on a
string derived from the file in such a way that the type it gives back is
`Fractional a => a' when it actually ought to be specified as returning a
`double'. However, this guess may be wrong.

> they seem to have bitten me hard. If anyone could point to the relevant
> information, it would be very nice.

I can't immediately think of a good source of information about type-class
issues in particular, but the gentle introduction and any haskell textbook
should mention it.

www.cs.bris.ac.uk/~tweed/pi.htm |tweed's law:  however many computers
email: tweed@cs.bris.ac.uk      |   you have, half your time is spent
work tel: (0117) 954-5250       |   waiting for compilations to finish.