Beginner's question about function signature

Viewed 54

I wrote the function pop as follows:

pop :: Int n => [a] -> n -> a
pop xs n = head $ drop n xs

When trying to run it, I get an error saying:

Expected kind '* -> Constraint', but 'Int' has kind '*'

However, changing the signature to

pop :: [a] -> Int -> a

Solves the issue. Why does this happen?

2 Answers

You are probably trying to generalize after seeing something like:

pop :: Num n => [a] -> n -> a

But Int and Num are very different things. Int is a type, it has values, it goes on either side of a function arrow ->. Num is a class which can be thought of as a "predicate on types", and it only makes sense to use it to the left of the context "fat arrow" =>. Num n means n is a numeric type. So Num Int is "true", Num Double is "true", Num String is "not true". It's not exactly like a function that can return true or false for each type, but that's one way to think about it.

(N.B. the way we usually talk about this is that there is an instance for Num Int, or Int is an instance of Num)

It's important to realize that the n variable here does not refer to a number but to a type. The value of n can be Int or Double or Rational (or, say, String, but that will fail to typecheck when it doesn't satisfy the Num class). pop is polymorphic and can have a whole bunch of different signatures, depending on context.

pop :: [Int] -> Int -> Int
pop :: [String] -> Int -> String
pop :: [[Bool]] -> Double -> [Bool]

-- possible, but invalid because Num String is not "True"
pop :: [Int] -> String -> Int  

See how these all match the pattern [a] -> n -> a for different choices of a and n? The Num n constraint says that only certain choices of n are valid. a is unconstrained, so you can choose whatever type you like.

Int is not a typeclass [Haskell-wiki], but a type, so it is

pop :: [a] -> Int -> a

A typeclass is a group of types, for example Integral is a typeclass. This is a group of types that are integral numbers. For example Int, Int32, Int64 and Integer are members of this typeclass. In order to be a member, one has to implement the methods the typeclass provides. For Integral that is for example quot, rem, etc.

Related