A Brief Tour of Haskell for Scala Programmers
Haskell is a purely functional programming language, it’s interesting to draw a comparison between Scala and Haskell to see how Scala’s hybrid functional / OO approach alters the way it expresses problems. Here’s a (very) brief overview of the language and how it compares against Scala.
Haskell and Scala have many similar features as both have clear functional concepts, however Haskell’s purely functional nature gives rise to a slightly simpler syntax in certain cases.
Definitions
Haskell handles all values and data as immutable structures, this means it can lazily evaluate expressions without fear of the underlying information changing.
val
, var
and def
don’t have any direct counterparts in Haskell since all evaluation of variables and functions are performed lazyily. In particular var
is the most removed from Haskell as it declares a mutable value.
Scala
Haskell
The most notable differences are the lack of initialisation keyword and the function type signature. In Haskell the type signature is seperate from the implementation, although the compiler will complain if an implemention is missing. All functions are curried in Haskell and the style of the type signature reflects this, sum takes an Int
and returns a function that takes another Int
. That function will perform the addition and return the summed value.
When it comes to defining values within functions its common to use where
and let
in Haskell. Let’s take a quick look.
or
Using where
both doubleA
and doubleB
are scoped to the entire function, the let
keyword by contrast is an expression in itself and scopes the definitions to everything after in
.
Function application
Function application in Haskell is done simply with juxtaposition and without any parentheses, if you do see parentheses it exists purely to handle execution precedence.
Scala
Haskell
Anonymous functions, currying, maps and filters
Haskell’s maps and filters achieve the same outcome as scala’s but are standalone functions opposed to scala collection methods. As a result they read in opposite directions. We can define lambda functions in Haskell using the \
character.
Scala
Haskell
There are more concise ways we can express the lambdas though in both Scala and Haskell
Scala
Haskell
In Haskell operators like *
and >
are functions that take two arguments. Because functions are curried in Haskell calling those operators with just one argument returns a function we can use nicely in our map
and filter
functions. We call this partial application, it’s worth remembering it because we’ll use it later.
I’ve also used the $
operator here, that’s a function application operator and importantly it’s right-associative. It’s the equivalent of writing something like this with parentheses.
Haskell
List comprehensions
We could also express the map and filter operations using a list comprehension.
Scala
Haskell
List comprehensions in Haskell have the output (or yield) to the left of the pipe |
, followed by our iterator definition. We can also add predicates into the comprehension to filter out certain values.
Let’s look at a slightly more indepth example. What about finding the length of the sides of a right angle triangle with total perimeter of 24?
Scala
Haskell
Pattern matching
Haskell offers pattern matching quite similar to Scala’s, but offers some nice syntatic sugar for pattern matching on function arguments. Let’s start by looking at a normal pattern match
Scala
Haskell
Its worth noting that strings are concatonated just like lists in Haskell using the ++
operator. We also have to explicitly convert length xs
to a string using the show
function.
The above examples seem pretty similar, but when we start looking at pattern matching on function arguments Haskell starts doing things a little differently.
Scala
Haskell
Haskell’s implementation is very clear and concise IMO. It’s also possible to add guards to the pattern match using the |
operator in haskell.
Scala
Haskell
Custom data types
Since Haskell is purely functional data structures are just representations of data, and do not contain methods like Scala’s classes, case classes and objects. It has however become quite common for scala developers to use case class
as a way to represent data structures with no methods, and since case classes are available for pattern matching they’re probably the best comparison to Haskell’s data
.
Scala
Haskell
It’s also possible to data types without naming the arguments, kind of like an inbetween of a tuple and a case class.
Haskell
Here we’re defining the data structure Point
as something which is created from 2 Float
arguments.
Pattern matching with these data structures is probably as you’d expect
Scala
Haskell
These data structures in Haskell are really just functions, so we get all of the benefits of functions in Haskell. Here we use partial application to produce a list of Citroen’s from 2000 - 2007.
Haskell
Conclusion
We’ve only covered a small part of both of these languages but it shows some of the basic syntactic differences between Haskell and Scala. The languages diverge further as we progress the conversation around data types and the type system, Haskell’s type system in particular is incredibly rich and provides excellent compiler feedback. Scala’s real world application is very compelling when compared to Haskell, access to Java libraries and industry tested frameworks and tools like akka and Apache Spark still make it a favourite for organisations like OVO looking for cutting edge technology with practical applications.