# Difference in Function typing in Haskell

• A+
Category：Languages

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 of any type `n` and returns a value of that 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.