Haskell is a programming language that was invented around 1990. It's named after the famous American logician Haskell Curry.
While not as popular as mainstream languages such as Python and C#, Haskell is still fairly widely used in the real world. On the site GitHut 2.0, which ranks programming languages according to their popularity on GitHub, Haskell was the 27th most popular language (by number of pull requests) in the first quarter of 2024.
Haskell is a purely functional programming language. That means that it has no mutable data, and so every Haskell function is actually a function in the mathematical sense. So Haskell doesn't have traditional loop statements such as 'while' and 'for'. In their place, we will generally use recursion or higher-order functions.
Haskell is a non-strict (= lazy)
language. In most programming languages, when you call a function
first the arguments are evaluated, and then the function is called.
In Haskell, the function is called first, and the arguments will be
evaluated only when necessary and only if necessary.
Actually you should already be familiar with this concept: for
example, the or
operator in Python is
non-strict. Consider this Python code:
x = 100 if x > 5 or long_calculation(): print('success')
When the code runs, long_calculation() will never be called. However, suppose that we define a function my_or in Python like this:
def my_or(a, b): return a or b
Now, let's rewrite the first block of code using my_or:
x = 100 if my_or(x > 5, long_calculation()): print('success')
When this code runs, long_calculation() will be called, since my_or() (like every function in Python) is strict, meaning that its arguments will be evaluated before it's called.
However, if you write the function my_or in
Haskell, it will be lazy, just like Python's or
operator. In fact every function in Haskell is lazy in this way.
Haskell's non-strict evaluation can dramatically improve the efficiency of some programs. For example, suppose that we write a Haskell function that recursively generates a list of all solutions to the N-queens problem for a given N. If we only want to find a single solution, we can simply take the head of that list. Then we'll get the first possible solution, and the remaining solutions (of which there could be exponentially many) will actually never be computed.
In fact, another consequence of non-strict evaluation is that in Haskell lists or other data structures may be infinite. As we will see, this is actually quite useful for some problems.
On the other hand, because of Haskell's non-strict evaluation, it is sometimes not so easy to understand the order in which Haskell will run different parts of your program, or even whether they will run at all. This is why we may call Haskell a non-procedural language.
You'll see that Haskell is quite different syntactically from C-like and Python-like languages. Instead, its syntax is similar to other functional languages such as ML and OCaml.
Programmers tend to have strong opinions about Haskell. Some people love it, and there's a strong online community of Haskell users. However, the language can be esoteric: it was designed by computer scientists and mathematicians, and some of the terminology in the language (especially in its libraries) comes from abstract algebra and category theory. This may seem strange at first.
The book Learn You a Haskell is freely available online, and is a great resource for learning Haskell at the introductory level. In many cases I won't give you detailed lecture notes for Haskell language features - instead, I'll just point you to chapters in this book.
There is really only one implementation of Haskell that everyone uses, namely GHC (the Glasgow Haskell Compiler). To install it, go to the download page and follow the instructions to run the GHCup installer.
Visual Studio Code works well for editing Haskell programs. If you use it, be sure to install the Haskell extension to get syntax highlighting and other useful editing features.
You can read about these subjects in Learn You a Haskell, chapters 1-4.