Welcome back to Haskell Function of the Day! Today we are going to look at a couple of easy to use higher order functions. Recall that a function is "higher order" if it takes a function as a parameter or returns a function as a result. You know about the 'take' function that returns the prefix of a list. > take 2 [1, 2, 3, 4, 5] [1,2] This is great if you have an integer holding the number of items you need. But what if you aren't sure how many items to take? The 'takeWhile' function uses a predicate to test each list element. It returns the elements from the front of a list as long as that predicate keeps returning True. For example > takeWhile (\x -> x == 5) [5, 5, 5, 1, 2, 3, 4, 5] [5,5,5] Here the predicate function is given as a lambda term '(\x -> x == 5)' meaning "function taking a parameter 'x' and returning the result of 'x == 5'. That predicate returns True for the first three elements of the list so that's the result of 'takeWhile.' Notice that the last 5 in the list is ignored because 'takeWhile' stops at first item for which the predicate fails. BTW we can abbreviate that lambda even further using partial application > takeWhile (==5) [5, 5, 5, 1, 2, 3, 4, 5] [5,5,5] Remember that '(==)' is the name of the function that tests two values for equality. It's a function with two parameters. We can fill in one of those parameters and get a function that takes just one remaining parameter. That's what the '(==5)' is about. It's the same as (\x -> x == 5) except shorter to type. To see a more compelling use of 'takeWhile' consider the earlier example of finding right triangles > let triangles = [(a, b, c) | c <- [1 .. 100], a <- [1 .. c], b <- [1 .. a], a*a + b*b == c*c] Suppose we only wanted the right triangles with a perimeter of at most 100. How many is that? We aren't sure. We could try > takeWhile (\(x,y,z) -> x + y + z <= 100) triangles [(4,3,5),(8,6,10),(12,5,13),(12,9,15),(15,8,17),(16,12,20),(20,15,25), (24,7,25),(24,10,26),(21,20,29),(24,18,30),(30,16,34),(28,21,35), (35,12,37),(36,15,39),(32,24,40),(40,9,41)] Here the lambda takes a triple (notice the pattern matching on the definition of that lambda's parameter!) and returns True only if the sum of the elements are less than or equal to 100. However this does assume the triangles in the 'triangles' list are in order of increasing perimeter. The way 'triangles' was generated doesn't seem to require that. We should sort them first. Using 'sortBy' to do that will be a topic of a future Haskell FotD. However, to explore the issue more, let's map the list of triangles to a list of triangle perimeters using the 'map' higher order function. We'll need a transformation function that computes the perimeter from the triple of side lengths > map (\(x,y,z) -> x + y + z) triangles [12,24,30,36,40,48,60,56,60,70,72,80,84,84,90,96,90,108,120,112,120,120, 126,132,140,144,132,156,154,150,144,160,168,176,168,180,168,180,192,180, 204,200,198,182,210,208,216,210,228,234,240,224] Inspecting this list of perimeters shows that they are, in fact, not completely sorted... but almost. And just to round things out... to go with 'takeWhile' there is also 'dropWhile' which does the obvious thing: it removes elements from the front of a list as long as some predicate says to do so. That's it for today's edition of Haskell Function of the Day. I hope you enjoyed it! Peter