Hello again and welcome back to Haskell Function of the Day! Today we're going to talk about a tricky function that I covered briefly in class: ($). Despite it's weird name the '$' function is no different than any other function. Let's ask ghci about its type > :type ($) ($) :: (a -> b) -> a -> b So the function takes two parameters. The first is a function from alpha to beta, the second is an alpha, and the overall result is a beta. Here "alpha" and "beta" are type variables that can be any type at all. What '$' does is apply its first parameter to its second. Notice that it's a higher order function since it takes a function as one of its parameters. To see it in action, let's define a couple of simple functions to play around with. > let inc x = x + 1 > let sum x y = x + y Now let's try something like > inc $ 5 6 The '$' function is an infix operator (like '+'). So in the example above it takes the 'inc' function and applies it to '5'. The result is, of course, 6. So how is this different than > inc 5 6 It is no different! So what's the point of '$'? Well... because it's an infix operator with right associativity and low precedence it allows you to write convenient expressions in various cases. Compare > inc (sum 2 3) 6 > inc $ sum 2 3 6 In the second case Haskell evaluation 'sum 2 3' first because the space "operator" has very high precedence (and '$' has very low precedence). The result, 5, is then used as the right operand to '$'. Notice how it is no longer necessary to parenthesize 'sum 2 3.' Let's look at some variations. > sum 2 $ inc 3 6 In this case 'sum 2' is evaluated as the left operand of '$' (space has very high precedence). Because of currying this returns a *function* that adds 2 to its one and only parameter. Next 'inc 3' is evaluated to a result of 4. Finally '$' is invoked and it applies the function 'sum 2' to 4, yielding 6. Compare this with > sum 2 (inc 3) 6 But what happens when we try to do fancy stuff with both arguments to sum? > sum $ inc 2 $ inc 3 Since '$' is right associative it will try to do 'inc 2 $ inc 3' first. The 'inc 2' yields 3 and the 'inc 3' yields 4 giving '3 $ 4' However this is an error since '3' is not a function. Thus: No instance for (Num (a1 -> a0)) arising from a use of `inc' Possible fix: add an instance declaration for (Num (a1 -> a0)) In the expression: inc 2 In the second argument of `($)', namely `inc 2 $ inc 3' In the expression: sum $ inc 2 $ inc 3 So it is necessary to write > sum (inc 2) $ inc 3 7 Where does '$' come in handy? It's useful when you chain a lot of functions together... not an unusual thing to do in a functional language. So for example suppose you wanted the sum of the second two elements of a list. Say you had a list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]. If you take the first four elements you get [1, 2, 3, 4]. If you then drop the first two elements from that list you get [3, 4]. Finally use the Prelude's 'sum' function on that list to get 7 (this is a different 'sum' than what I was talking about before so I need to restart ghci to erase that earlier definition). > let myList = [1..10] > sum (drop 2 (take 4 myList)) 7 This can be more neatly written > sum $ drop 2 $ take 4 myList 7 Read this from the right to the left (because '$' has right associativity). First 'take 4 myList' is evaluated. Next 'drop 2' is evaluated returning a function that drops two things from it's (single) parameter. This is the magic of partial evaluation. Next the right hand '$' applies 'drop 2' to 'take 4 myList' to get the list you want. Finally the left hand '$' applies sum to that list. This gives you a pipeline-like effect where each stage of the pipeline processes the results of the stage to the right. The cool part about this is that there is nothing special about the '$' function, particularly. If Haskell didn't come with it, you could define it yourself. That's it for today's edition of Haskell Function of the Day. I hope you enjoyed it! Peter