I have been learning Haskell for a while. The more I am exposed to this language, the more I am amazed by the elegance of the functional programming paradigm. List comprehension is one of the beautiful things that I like in Haskell. Coming from Python, I am familiar with it. But the list comprehension in Haskell feels more natural because it is closer to what you would write in mathematics.
For example, in Python, multiple predicates in a list comprehension expression
must be connected with logical operators. I can understand that is designed to
be intuitive. But when you have many predicates nested under several
for
-expressions and if
-expressions within a list comprehension, it can be
ugly and difficult to read. I’m not saying list comprehension isn’t good in
Python; it is good and powerful if you keep it simple. But in comparison,
Haskell connects multiple predicates with commas and allows parallel
comprehension (saves your a line of import itertools
). This allows Haskell to
be capable of doing complicated list comprehensions well without losing
clarity.
A Haskell example I’d like to show is a naive implementation of the Sieve of Eratosthenes. With list comprehension, everything can fit into one line excepting the type declaration.
sievePrime :: Int -> [Int]
sievePrime n = [x | x <- [2..n], and [x `mod` y /= 0 | y <- [2..floor(sqrt(fromIntegral x))]]]
The equivalent Python version would be
def sievePrime(n):
return [x for x in range(2, n + 1) if all([x % y != 0 for y in range(2, int(x ** 0.5))])]
I feel that <-
in Haskell is more elegant than for ... in ...
in Python.
The Haskell and
, when used on a list, is equivalent to Python all()
. The
only thing I’m still struggling to get used to in Haskell is the lack of C-like
implicit type promotion, i.e., you cannot simply add an integer and a
floating-point number, unless the integer is cast to a floating-point number
first to match the type signature of the operator. This means that an explicit
type conversion using fromIntegral
must be performed when applying sqrt
on
an integer here.