Brent Yorgey byorgey at seas.upenn.edu
Fri Mar 27 09:07:10 EDT 2009

```On Thu, Mar 26, 2009 at 10:01:07PM +0000, Ivan Moore wrote:
> Hi all,
>
> consider this very small function:
>
> thing n = n + round(sqrt n)

Here's what's going on: since you call sqrt on n, it must have some
type which is an instance of Floating.  However, round can return any
type which is an instance of Integral, and since you are adding n to
it, n must have the same type.

This is the takeaway point here: sqrt requires some floating-point
type (like Float or Double), but round returns an Integral type (like
Int or Integer) and n can't be both.  In particular you can't call
sqrt on an Integral value.  So the fix is to use fromIntegral to
convert:

thing n = n + round (sqrt (fromIntegral n))

>
> It loads into ghci with no warnings.

The reason (which is a bit confusing) is that it typechecks just
fine---if there *were* a type which is an instance of both Integral
and Floating (and I guess round needs RealFrac as well), n could have
that type.  There isn't such a type in the standard libraries, but in
theory you could make up your own type which is an instance of both.

> When I try to run "thing 10" I get:
>
> [1 of 1] Compiling Main             ( C:\temp\statictype.hs, interpreted )
> *Main> thing 10
>
> <interactive>:1:0:
>     Ambiguous type variable `t' in the constraints:
>       `Integral t' arising from a use of `thing' at <interactive>:1:0-7
>       `RealFrac t' arising from a use of `thing' at <interactive>:1:0-7
>       `Floating t' arising from a use of `thing' at <interactive>:1:0-7
>     Probable fix: add a type signature that fixes these type variable(s)
>
> I have tried to add various type signatures (without really knowing
> what I'm doing!) and haven't been able to get it to work.
>
> I am confused about a few things related to this:
> (a) what type signature fixes it and why it needs any help - it looks
> like the sort of thing that type inference shouldn't need any help
> with

signature would only help if you actually had some type which was both
Integral and Floating, but you don't.

> (b) it looks like a runtime type error and I thought you didn't get
> runtime type errors in Haskell

You don't.  This isn't a runtime type error; the error was generated
while trying to typecheck the expression 'thing 10' before evaluating
it.

> (c) if I substitute 10 for n and do "10 + round(sqrt 10)" I get the

This is because numeric literals (like 10) are polymorphic---they can
have any numeric type.  In this case, type inference correctly figures
out that the first 10 should have type Integer, and the second 10
should have type Double.  The difference is that they are not
constrained to have the same type---unlike the two occurrences of 'n'