Point-free baby-steps in Haskell

we7‘s study group (still aka Nerd Club) has moved onto a bit of Haskell with Learn You a Haskell for Great Good. The chapter on higher order functions introduces this definition:

numLongChains :: Int
numLongChains = length (filter isLong (map chain [1..100]))
    where isLong xs = length xs > 15

For some reason I immediately wanted to factor the thing as a function taking isLong as a parameter:

numLongChains` :: (Integral a) => ([a] -> Bool) -> Int
numLongChains` isLong = length (filter isLong (map chain [1..100]))

(Forgive the backwards ‘prime’ symbols, apparently my blog’s syntax highlighting plugin can’t handle an apostrophe as part of a name.)

A quick check satisfied me that it worked

*Main> numLongChains
66
*Main> let longFunc xs = length xs > 15
*Main> numLongChains' longFunc
66

and then I carried on reading. It turns out to have been quite an instructive thing to do, as in the next sections I learned how to pass a lambda rather than a named function

*Main> numLongChains' (\xs -> length xs > 15)
66

and finally on to using function composition, giving, to my newly opened eyes, the most convenient way yet:

*Main> numLongChains' $ (> 15) . length
66

After that, we’re introduced to point-free (pointfree? point free?) style, and so I wondered how I’d turn my numLongChains' function point-free. I struggled making no progress for a couple of hours, and had to give up until the group met to discuss the chapter. Chris Nix pointed out that I’d need a flip on the filter to get the arguments in the right order, and after a bit more playing I arrived at:

numLongChains```` :: (Integral a) => ([a] -> Bool) -> Int
numLongChains```` = length . flip filter (map chain [1..100])

I’m really pleased to get to the right answer, but mostly I’m just shocked to discover a way of thinking about computation that’s so new and alien. I know it’d take me hours to come up with point-free versions of even simple functions. While trying to work out my example I found this topic which demonstrates a ton of techniques that I just hadn’t appreciated were out there. It’s less of an “Aha!” moment as things drop in to place, and more of a “Woah!” moment as a small crack appears and I glimpse strange beasts on the other side. I’m putting this aside for a while as we move on with the basics of Haskell, but I know I’ll be back someday.

Leave a Reply

Your email address will not be published. Required fields are marked *