Haskell: foldl via foldr (part III)

As I thought about last night’s post, I was bothered by how confusing it seemed and I finally decided that the reason is that I never directly addressed what was happening.  Yes, I provided an expansion and mentioned the idea of partial function invocation but I never really generalized this idea.  So today seems as good a time as any…

In Haskell, when we talk about partial function execution or “currying” we’re referring to the idea that a function with two or more parameters can receive some of it’s parameters now and others later.  Take a look at the following function declaration (the declaration is the first line, the definition is the second line):

myFunc :: (Num a) => a -> a -> a

myFunc a b = a * b

What this function declaration tells us is that myFunc takes a parameter of type a and a second parameter of type a and returns a result of type a.  But there is more going on here.  Look at how we define the final returns: ->  Why would we use this same symbol between the first and second parameters?  The reason is that the definition is telling us something very deep about how Haskell approaches functions – what it’s really saying is that myFunc accepts a parameter of type a and returns a result that is a function.  This resulting function accepts a parameter of type a and returns a result of type a.

Let’s rewrite the function declaration to perhaps make this point a bit more clear:

myFunc :: (Num a) => a -> (a -> a)

myFunc a b = a * b

we could “curry” or partially execute this function with the following expression:

(myFunc 7)

This expression yields a function that will accept any value and multiply it by 7 – all it needs is that second parameter.  Now don’t be fooled into thinking this is a simple parlor trick and that all we’ve really done is put parentheses in an odd place.  Haskell allows us to pass this “curried” function as a parameter to any function that accepts a function argument that is required to accept a Num and return a Num.

We can do the same thing with the built in * function:

((*) 7)

Placing the * operator in parentheses like this simply allows us to treat it like a ‘normal’ function with two following parameters.  In our expression, we provide it with a value of 7 for the first of these two parameters.  When we later use this function by providing it with a Num for its second parameter, it will return that value multiplied by 7.

Again, this isn’t just a shell game – this is how work gets done in Haskell.  Consider the map function which takes a function and applies it to every member of a list to generate a new list.  The function that it accepts as a parameter is required to consume one parameter and return one result.  If we wanted to use map to multiply ever member of a list containing [1,2,3] by 7 then we could simply say:

map ((*) 7) [1,2,3]

this should give us the result [7, 14, 21] (and, in fact, if we try this out in ghci, this is exactly the result that we get).

Now sure we could have written a function that took a number and multiplied it by seven and then passed that function to map but, for a one-off application, sometimes it’s more straightforward to implement it directly like this.  And, yes, this example is trivial but it highlights the capabilities that come from Haskell’s partial execution feature.

Leave a comment