Second order functions
16 July 2009In Haskell there are second order functions, which is when functions take other functions as parameters. To show its usefulness consider the built-in function map which applies a function to every element within the list; in the example below
[1,2,3,4]
becomes [2,4,6,8]
:
double :: Int -> Int double x = x*2 map double [1,2,3,4]
Now suppose you wanted to apply a threshold to a list of numbers. Naturally you would define a function that takes both the threshold value and the value to be checked:
threshold :: Int -> Int -> Int threshold limit x | x < limit = 0 | otherwise = x
However unlike double, threshold takes two parameters. This is not a problem as in Haskell you can create a 1-variable function by filling in the earlier parameters. Hence to calculate [0,0,0,0,5,6,7,8]
from [1,2,3,4,5,6,7,8]
you can use:
map (threshold 5) [1,2,3,4,5,6,7,8]
This is an examples of partial evaluation, and it is very useful. To demonstrate this usefulness, I was recently writing in Python a tokeniser. Tokenisers are normally implemented using switch statements; however Python does not have switch statements, so they have to be emulated using functions and dictionaries (dictionaries are basically hash-tables)
token = { '"' : readString, '$' : readVariable, '(' : readSymbol, ')' : readSymbol, ';' : readSymbol }[char]()
The problem arose because readSymbol was a special case where I wanted to pass forward the current character as an extra parameter, and I definitely did not want to use an if-then-else chain. Mercifully Python's lambda function can perform what amounts to partial evaluation:
token = { '"' : readString, '$' : readVariable, '(' : lambda : readSymbol(extraParam), ')' : lambda : readSymbol(extraParam), ';' : lambda : readSymbol(extraParam) }[char]()
(16th July 2009)