Ivan Moore ivan.r.moore at gmail.com
Fri Mar 27 15:44:05 EDT 2009

```Many thanks for the fantastic answers.

> 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.

If there were such a type, could "10" have that type and then would my
problem have not existed? (in which case, why doesn't it!?)
(an answer of - "ask again when you've used the language a bit more"
would be perfectly fine if it requires a lot
more understanding of the language to understand the answer than a
newbie like me has - I'm just curious)

On Fri, Mar 27, 2009 at 1:07 PM, Brent Yorgey <byorgey at seas.upenn.edu> wrote:
> 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'
>
> Confusing, isn't it!  It's a shame that numeric types can be so
> confusing, since that's usually one of the first things that people
> run into when learning the language.  But I hope this is helpful.
> Feel free to ask if you have more questions.
>
> -Brent
> _______________________________________________
> Beginners mailing list