RandomSlices.com

(refresh for a different slice)


Comprehensions in Haskell and Python

It's been another long hiatus, but today I finally found the inspiration I needed to post another brief article. Owing to my interest in functional programming, I've been (slowly) learning some Haskell, and today I managed to find some more time to continue that endeavor. My favorite resource so far has been Learn You a Haskell for Great Good!: A Beginner's Guide. Today I was thrilled to discover that Haskell also supports one of my favorite Python features, list comprehensions, and that the syntax isn't too terribly foreign.

While working through the list comprehension examples in Great Good!, I came across one in particular that piqued my interest - a function with only a list comprehension as the body, and with a function parameter acting as the input iterable to the comprehension. Here's a toy example, similar to the one in Great Good!, of such a function that accepts a list of numbers as its input and produces a list with values that are double the odd numbers greater than 10 in the input:

doubleOddGreaterThan10 il = [ if x > 10 then x*2 else x | x <- il, odd x]

If you're not familiar with Haskell the syntax might seem a bit strange, but I'm betting that if you're familiar with Python list comprehensions you won't find it too hard to parse. Here's an example of invoking this function with a list of integers from 2 to 20 as the input:

doubleOddGreaterThan10 [2..20]

[3,5,7,9,22,26,30,34,38]

I was intrigued because I hadn't thought about using a function argument as the input to a comprehension before. So I fired up the IPython REPL and quickly confirmed that I could create the equivalent function in Python, and with syntax that's just about as concise as Haskell's:

odd = lambda x: x % 2 == 1

double_odd_greater_than_10 = \  
    lambda il : [x*2 if x > 10 else x for x in il if odd(x)]

As expected, our Python version gives us the same result as the Haskell version, provided that we are careful to note that a Haskell list expressions like [2..20] defines a closed interval, whereas Python's range function yields a half-open interval.

double_odd_greater_than_10(range(2,21))

[3, 5, 7, 9, 22, 26, 30, 34, 38]

It was really nice to discover this early in my Haskell education that learning me a Haskell can do my Python functional programming some great good!

comments powered by Disqus