Haskell/More on functions
From Wikibooks, the open-content textbooks collection
As functions are absolutely essential to functional programming, there are some nice features you can use to make using functions easier.
[edit] Private Functions
Remember the sumStr function from the chapter on list processing. It used another function called addStr:
addStr :: Float -> String -> Float addStr x str = x + read str sumStr :: [String] -> Float sumStr = foldl addStr 0.0
So you could find that
addStr 4.3 "23.7"
gives 28.0, and
sumStr ["1.2", "4.3", "6.0"]
gives 11.5.
But maybe you don't want addStr cluttering up the top level of your program. Haskell lets you nest declarations in two subtly different ways:
sumStr = foldl addStr 0.0
where addStr x str = x + read str
sumStr =
let addStr x str = x + read str
in foldl addStr 0.0
The difference between let and where lies in the fact that let foo = 5 in foo + foo is an expression, but foo + foo where foo = 5 is not. (Try it: an interpreter will reject the latter expression.) Where clauses are part of the function declaration as a whole, which makes a difference when using guards.
[edit] Anonymous Functions
An alternative to creating a named function like addStr is to create an anonymous function, also known as a lambda function. For example, sumStr could have been defined like this:
sumStr = foldl (\x str -> x + read str) 0.0
The bit in the parentheses is a lambda function. The backslash is used as the nearest ASCII equivalent to the Greek letter lambda (λ). This example is a lambda function with two arguments, x and str, and the result is "x + read str". So, the sumStr presented just above is precisely the same as the one that used addStr in a let binding.
Lambda functions are handy for one-off function parameters, especially where the function in question is simple. The example above is about as complicated as you want to get.
[edit] Infix versus Prefix
As we noted in the previous chapter, you can take an operator and turn it into a function by surrounding it in brackets:
2 + 4 (+) 2 4
This is called making the operator prefix: you're using it before its arguments, so it's known as a prefix function. We can now formalise the term 'operator': it's a function which entirely consists of non-alphanumeric characters, and is used infix (normally). You can define your own operators just the same as functions, just don't use any alphanumeric characters. For example, here's the set-difference definition from Data.List:
(\\) :: Eq a => [a] -> [a] -> [a] xs \\ ys = foldl (\zs y -> delete y zs) xs ys
Note that aside from just using operators infix, you can define them infix as well. This is a point that most newcomers to Haskell miss. I.e., although one could have written:
(\\) xs ys = foldl (\zs y -> delete y zs) xs ys
It's more common to define operators infix. However, do note that in type declarations, you have to surround the operators by parentheses.
You can use a variant on this parentheses style for 'sections':
(2+) 4 (+4) 2
These sections are functions in their own right. (2+) has the type Int -> Int, for example, and you can pass sections to other functions, e.g. map (+2) [1..4].
If you have a (prefix) function, and want to use it as an operator, simply surround it by backticks:
1 `elem` [1..4]
This is called making the function infix: you're using it in between its arguments. It's normally done for readability purposes: 1 `elem` [1..4] reads better than elem 1 [1..4]. You can also define functions infix:
elem :: Eq a => a -> [a] -> Bool x `elem` xs = any (==x) xs
But once again notice that in the type signature you have to use the prefix style.
Sections even work with infix functions:
(1 `elem`) [1..4] (`elem` [1..4]) 1
You can only make binary functions (those that take two arguments) infix. Think about the functions you use, and see which ones would read better if you used them infix.
| Exercises |
|---|
|

