Hugs type signature contains extra type constraints?

159 views Asked by At

Came across this while playing with Haskell and I'm stumped:

Hugs> :type (\x -> x^2)
\x -> x ^ 2 :: (Integral a, Num b) => b -> b

What is a doing in there? How am I supposed to read that? If I type the same thing into GHCi, it gives me the output I would expect:

Prelude> :type (\x -> x^2)
(\x -> x^2) :: Num a => a -> a

Is this a bug in Hugs?

2

There are 2 answers

2
hammar On BEST ANSWER

The Integral constraint comes from the exponent of 2. Remember that in Haskell, integer literals are actually polymorphic values of type Num a => a. The compiler then infers that since it's being used as an exponent to (^) :: (Num a, Integral b) => a -> b -> a, it must be of the more constrained type Integral a => a.

To save you from having to disambiguate numeric literals all over your code, Haskell uses type defaulting to pick a reasonable concrete type for any unconstrained numeric types. In this case, that will be Integer. The difference seems to be that :type in Hugs reports the inferred type before this happens, while GHCi reports the type after type defaulting has been applied.

If you specify a concrete type for the exponent yourself, the extra constraint disappears.

Hugs> :type (\x -> x^(2 :: Integer))
\x -> x ^ 2 :: Num a => a -> a
1
Jeff Burka On

This is sort of speculation, but this might have to do with the type of (^). :t (^) in ghci returns (^) :: (Num a, Integral b) => a -> b -> a. I'm guessing hugs sees that the second argument of ^ needs to be an Integral, and even though that argument is just a constant 2, it includes the constraint in the type signature.