- A+

I've been playing around with basic functions in Haskell, and am a little confused with the difference between the following type declarations for the function `f`

`f :: Integer -> Integer `

versus

`f :: Integral n => n -> n `

So far, I've treated both of these as identical, but I'm sure this isn't true. What is the difference?

**Edit:** As a response to the first answer, I wanna propose a similar example which more is along the lines of the question I hold.

Consider the following declarations

`f :: Num n => n -> n `

or

`f :: Num -> Num `

What functionality does each offer?

Let's rename:

`f :: Integer -> Integer g :: (Integral n) => n -> n `

I like to follow a fairly common practice of adding parentheses to the constraint section of the signature. It helps it stand out as different.

`f :: Integer -> Integer`

is simple, it takes an integer and returns another integer.

As for `g :: (Integral n) => n -> n`

: `Integral`

is not a type itself, rather it's more like a predicate. Some types are `Integral`

, others aren't. For example, `Int`

is an `Integral`

type, `Double`

is not.

Here `n`

is a *type variable*, and it can refer to any type. `(Integral n)`

is a *constraint* on the type variable, which restricts what types it can refer to. So you could read it like this:

`g`

takes a value ofany type`n`

and returns a value ofthat same type, provided that it is an`Integral`

type.

If we examine the `Integral`

typeclass:

`ghci> :info Integral class (Real a, Enum a) => Integral a where quot :: a -> a -> a rem :: a -> a -> a div :: a -> a -> a mod :: a -> a -> a quotRem :: a -> a -> (a, a) divMod :: a -> a -> (a, a) toInteger :: a -> Integer {-# MINIMAL quotRem, toInteger #-} -- Defined in ‘GHC.Real’ instance Integral Word -- Defined in ‘GHC.Real’ instance Integral Integer -- Defined in ‘GHC.Real’ instance Integral Int -- Defined in ‘GHC.Real’ `

We can see 3 builtin types which are `Integral`

. Which means that `g`

*simultaneously* has three different types, depending on how it is used.

`g :: Word -> Word g :: Integer -> Integer g :: Int -> Int `

(And if you define another `Integral`

type in the future, `g`

will automatically work with that as well)

The `Word -> Word`

variant is a good example, since `Word`

s cannot be negative. `g`

, when given a positive machine-sized number, returns another positive machine-sized number, whereas `f`

could return any integer, including negative ones or gigantic ones.

`Integral`

is a rather specific class. It's easier to see with `Num`

, which has fewer methods and thus can represent more types:

`h :: (Num a) => a -> a `

This is also a generalization of `f`

, that is, you could use `h`

where something with `f`

's type is expected. But `h`

can also take a complex number, and it would then return a complex number.

The key with signatures like `g`

's and `h`

's is that they work on multiple types, as long as the return type is the same as the input type.