babon
babon

Reputation: 3774

Regarding Haskell type classes (Num vs Read)

Can someone please explain what I am missing here:

Prelude> :t read
read :: (Read a) => String -> a 
Prelude> read "4"

<interactive>:1:0:
    Ambiguous type variable `a' in the constraint:
      `Read a' arising from a use of `read' at <interactive>:1:0-7
    Probable fix: add a type signature that fixes these type variable(s)

read "4" raises an error as ghci doesn't know which concrete type we want, it only knows that we have a Read type class. read "4" :: Int works fine. This is clear to me.

Now, following the above logic, I expected fromIntegral 4 to raise an error:

Prelude> :t fromIntegral
fromIntegral :: (Integral a, Num b) => a -> b
Prelude> fromIntegral 4
4

However, it works fine. Why is a type annotaion NOT required in this case? I expected the above to fail; and ONLY

Prelude> fromIntegral 4 :: Int

to work.

NB - I am reading "Learn you a Haskell for great good" and have covered till chapter 5. Is what I am asking discussed in chapter 7 (or some other chapter)?

Thanks.

Upvotes: 8

Views: 163

Answers (2)

hammar
hammar

Reputation: 139930

It works because of type defaulting, which causes ambiguous type variables to be defaulted to Integer or Double (or some other user-defined default). This only happens for Num and its subclasses.

In GHCi, the rules for defaulting are relaxed to also work for Show, Eq and Ord, and also () is added to the list of default types. This allows expressions like [] == [] to type check.

Upvotes: 12

Ingo
Ingo

Reputation: 36339

Difference is that read could potentially result in any type, whereas fromIntegral yields a number. There is some defaulting going on with regard to numbers in ghci, so that ghci can just use the default type.

Upvotes: 4

Related Questions