Learn Me a Haskell
Alrighty, so, week two of my attempt to learn Haskell. Today, I had a read through Learn You a Haskell, getting through the first section of it. “Learn you a Haskell” is a guide written for newcomers to Haskell which was recommended by Reddit’s Haskell Community (along with a few others, this handy link). It’s fairly straightforward to follow, which is good, and introduces a new way of solving problems: list comprehensions.
I’ve never really bothered with the concept in Python (even though we get generators, which are extremely similar), but I can see how they can be useful for limited problem sets. Once I’d read through the guide, I had a crack at a few problems off Project Euler, focussing on using list comprehensions to solve them.
One such problem was to “Find the sum of all the multiples of 3 or 5 below 1000”; it sounds fairly simple, right? In Python (or another imperative language), you might write that out as:
sum = 0
for i in xrange(0, 1000):
if i % 3 == 0 or i % 5 == 0:
sum += i
That’s an imperative, brute-force solution and… well, it’s wordy. You could write that much more cleanly using the equivalent list comprehensions (in both Haskell, or Python):
-- Haskell
sum [ x | x <- [1..999], x `mod` 3 == 0 || x `mod` 5 == 0]
sum([x for x in range(1,999) if x % 3 == 0 or x % 5 == 0])
These solutions appear far more complex syntactically, but it’s cleaner when you know what it’s doing, so let’s break that down. The form [ x | x <- something, condition ] can be read as select x from this range where ... - just like SQL (or LINQ, if you’re that way inclined). It’s a form you might recognise from set notation, too, as it closely mimics that (especially in Haskell). So, in short, what that’s saying is choose x from the range 1 to 1000, where the modulus of x by 3 (or 5) is 0. Simple, right? We then pass that list to the sum function, and we’re done.
I reckon so. There’s some syntactical sugar there which needs explaining though, so let’s look at that. Most importantly, the backticks (`) around the word mod - are confusing at first, but are an interesting part of Haskell’s syntax. Haskell is a language in which you normally call functions in a prefix style (same as most, really):
# Python (or any language, really)
myFunc(1, 2)
mod(3, 5)
-- Haskell
myFunc 1 2
mod 3 5
Of course, with Haskell, there’s no parentheses (it’s more like Lisp in terms of calling functions), but you can see it’s essentially the same style. Unfortunately, however, mod 3 5 isn’t particularly clear - are you getting the modulus of 3 by 5, or 5 by 3? Putting backticks around a function let’s you call it in an infix manner - so 3 `mod` 5 - which makes it much, much easier to see what you’re doing. Of course, it’s only really useful in a limited set of cases, but it’s useful nonetheless.
Tags: