Fun with Haskell
My interest in Haskell arose while studying functional programming in Lisp. While Lisp is not used as widely today, languages like Haskell, Scala & Clojure are fairly prominent. Haskell seemed to be the most unique & interesting to me as it is a pure & lazy FP language. I also really enjoyed some quirky yet intriguing videos by Simon Peyton Jones on Haskell & its history. He often talks about 3 of his mottos that he developed while working on Haskell: - Purity is embarassing - Laziness is cool - Success should be avoided at all costs
So I wanted to give Haskell a try & started reading this funky book called “Learn You a Haskell” which is freely available online. I’m roughly halfway into the book & wanted to talk about some cool Haskell features I’ve learned so far.
Haskell reads like math
Haskell’s list comprehensions tend to remind me a lot of my high school math books. For eg., to take a list of numbers from 1 to 10 & multiply them by 2, you simply write :
[x*2 | x <- [1..10]]
The ease with which you can express mathematical problems in Haskell so succintly just blows me away sometimes! Here’s a one liner to find the no of right triangles where each side has an integer length less than or equal to 10 :
rightTriangles = [(a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10], a^2 + b^2 == c^2]
Here’s another one line function to calculate the length of a list :
length xs = sum [1 | _ <- xs]
_ symbol means we don’t care about the value of the specific list element
Haskell has type inference
While a function like
factorial n = product [1..n] will work perfectly fine in Haskell, we can add a type signature to our function definition as well which makes the function more readable :
factorial :: Integer -> Integer factorial n = product [1..n]
Recursion feels so natural
Haskell is built for recursion. Here’s a simple function to reverse a list, using the
++ list append operator.
 refers to the empty list which is the base case when doing recursion on lists :
reverse  =  reverse (x:xs) = reverse' xs ++ [x]
Let’s take a loot at the popular quicksort algorithm to sort lists in Haskell :
quicksort  =  quicksort (x:xs) = smallerSorted ++ [x] ++ biggerSorted where smallerSorted = quicksort [a | a <- xs, a <= x] biggerSorted = quicksort [a | a <- xs, a > x]
Pattern Matching rocks
We can rewrite the factorial function above in a recursive style as well, starting with the base case first, and then writing the inductive case :
factorial 0 = 1 factorial n = n * factorial (n - 1)
This feels more natural, and more math-y! The
length function from above can also be re-written like this :
length :: [a] -> Int length  = 0 length (_:xs) = 1 + length xs
a (sometimes pronounced as alpha by ML hackers) is a type variable that can have any type. It makes the function
length more powerful as it can take a list of any data type as input, but the function will always return a value of type
Build using Higher order functions
Haskell comes with built-in support for a lot of high level functions like map, filter, fold (foldl, foldr), zip, etc.
To find the largest number under 100,000 that’s divisible by 3829, we can make use of Haskell’s laziness as :
largestDivisible = head (filter p [100000,99999..]) where p x = x `mod` 3829 == 0
Although we pass an infinite list, due to Haskell’s laziness, evalutation will stop once we find the
head ie first element of the list that satisfies the filter.
Here’s another example using map, to find the sum of all odd squares that are smaller than 10,000 :
sumOddSq = sum (takeWhile (<10000) (map (^2) [1, 3..]) )
This was a quick summary of some interesting programming ideas that I’ve seen in Haskell so far. Although I know I’ve barely scratched the surface here, I’m yet to study more advanced concepts like monads, typeclasses, monoids & dealing with laziness. I’ll try & share my learnings of these topics as I go along.
PS - If you’re interested in functional programming, I’ll highly recommend the Programming Languages MOOC by Prof Dan Grossman. While the course uses Standard ML to teach statically typed functional programming (Part A), most concepts were taught in such a generalized manner that I could easily apply them to Haskell as well !!
PPS - Special thanks to the Reddit User u/Noughmare for helping me fix bigs in this article!
5 books to offer a different perspctive on life
Why do many companies still ask CS puzzle type questions in their coding round for DS roles
Looking at the design recipes for 2 common sorting algorithms in Scheme
Don’t teach yourself data science in 10 days, but in 10 years
Some valuable lessons I learnt in my recent job search experience
And why you don’t need another ‘How to become a data scientist in 2021’ listicle
An intuitive way to look at matrix vector multiplication, with applications in image processing
Most tech firm interviews include SQL problems for DS roles, so how should you prepare for them?
Implementing basic matrix algebra operations in Scheme using a Jupyter notebook
Building a gender classifier model based on the dialogues of characters in Hollywood movies
Simple EDA of my reading activity using tidyverse on R Markdown
My experience using productivity tools for personal projects
Comparing Tree Recursion & Tail Recursion in Scheme & Python
My notes halfway through the book Learn You A Haskell
My topsy turvy ride to data science
Books, MOOCs and other resources that I would highly recommend
The magic of SICP