Haskell functions and currying

Viewed 77

I am tryng to learn Haskell and have begun reading a book on it. It seems pretty interesting and want to continue my journey even if it's hard to grasp at first. I have this piece of code and I want to understand why it works.

names = [("Ian", "Curtis"), ("Bernard", "Summer"), ("Peter", "Hook"), ("Stephen", "Morris")]

compareLastNames name1 name2
  | lastName1 > lastName2 = GT
  | lastName1 < lastName2 = LT
  | otherwise = EQ
  where
    lastName1 = snd name1
    lastName2 = snd name2

main = do
  print (sortBy compareLastNames names)

What I don't understand is compareLastNames takes two arguments but even if I pass it a list of tuples, it just works. I know haskell curries functions but how does it work. How is it possible for the function to accept a list of tuples and not throw an error?

2 Answers

Currying has nothing to do with this.

In (sortBy compareLastNames names) you call function sortBy passing two arguments: compareLastNames (a function) and names (a list of pairs). This does not directly call function compareLastNames in any way; in partcular, this function is not passed names as an argument -- that would be a type error, as you realized.

The function compareLastNames is only called inside the definition of sortBy, which will provide it with arguments of the right type (two pairs).

To stress the point, consider this:

foo :: (String -> Int) -> Int -> Int
foo g x = x + g "abcde"

myG :: String -> Int
myG = length

test :: Int
test = foo myG 42

Here we do not call myG with 42, which is not a string. Instead, we evaluate test as:

test
= foo myG 42
= 42 + myG "abcde"
= 42 + 5
= 49

The key point to understand here is that we pass myG as a function value, not the result obtained by applying it to some other value. Passing the unapplied myG allows foo to choose the argument for myG.

You are not passing a list of tuples to compareLastNames.

You are calling sortBy with the two arguments, compareLastNames and names.

sortBy, in turn, uses compareLastNames to compare any pair of elements from names as it needs to, as it sorts it, using compareLastNames as the comparing predicate.

Related