First steps with Haskell
Tags: haskell
Published: 2020-08-19 05:02:12

This is my first article at **Dev.to**. I'm not used to writing in English, but I am thinking of get some practice while learning pure functional programming with **Haskell**.

Haskell is a 90's programming language characterized by:

- Multi OS (Windows, Mac, Linux)
- General purpose (like C#, Java, C, C++)
- Purely functional (like Elm)
- Strong static typing (like Java, C, C++)
- Type inference (like OCaml, Haskell, Scala, Kotlin)
- Lazy evaluation
- Concise programs

Haskell has a diverse range of use commercially, from aerospace and defense, to finance, to web startups, hardware design firms and lawnmower manufacturers ([Haskell Wiki](https://wiki.haskell.org/Haskell_in_industry))

The language is widely known as a functional programming language which is great to write pure code and immutable data structures. It has a great support for a wide variety of concurrency models too.

**Functional programming** is a style of programming in which the basic method of computation is the application of functions to arguments, encouraging us to build software by composing functions in a declarative way (rather than imperative), avoiding shared state and mutable data.

In a **pure functional language**, you can't do anything that has a side effect. As a benefit, the language compiler can be a set of pure mathematical transformations. This results in much better high-level optimization facilities. 

A **side effect** would mean that evaluating an expression changes some internal state that would later cause evaluating the same expression to have a different result. In a pure functional language we can evaluate the same expression as often as we want with the same arguments, and it would always return the same value, because there is no state to change. ([What does “pure” mean in “pure functional language”?](https://stackoverflow.com/questions/4382223/what-does-pure-mean-in-pure-functional-language))

In Haskell, even functions based on system inputs and outputs (like `print`, `getChar` and `getSystemTime`) are pure. They handle `IO` actions (where IO is a _monad_, like Javascript `Promises` is) which can be combined and performed by runtime. We can say that `getSystemTime` is a constant which represents the action of getting the current time. This action is the same every time no matter when it is used. ([IO Inside](https://wiki.haskell.org/IO_inside))

A language is **statically typed** if the type of a variable is known at compile time. For some languages this means that you as the programmer must specify what type each variable is (e.g.: Java, C, C++); other languages offer some form of *type inference*, the capability of the type system to deduce the type of a variable.

The main advantage here is that all kinds of checking can be done by the compiler, and therefore a lot of trivial bugs and a very large class of program errors are caught at a very early stage. ([What is the difference between statically typed and dynamically typed languages?](https://stackoverflow.com/questions/1517582/what-is-the-difference-between-statically-typed-and-dynamically-typed-languages/))

**Lazy evaluation** means that expressions are not evaluated when they are bound to variables, but their evaluation is deferred until their results are needed. When it is evaluated, the result is saved so repeated evaluation is not needed.

Lazy evaluation is a technique that can make some algorithms easier to express compactly and much more efficiently. It encourages programming in a modular style using intermediate data structures, and even allows data structures with an infinite number of elements. ([Programming in Haskell](https://www.cs.nott.ac.uk/~pszgmh/pih.html))

Imagine an infinite data structure like a **Fibonacci list**. We don't actually figure out what the next element is until you actually ask for it. ([Fibonacci, Using Lazy Evaluation](https://riptutorial.com/haskell/example/12240/fibonacci--using-lazy-evaluation))

```haskell
let fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
take 10 fibs        -- [0,1,1,2,3,5,8,13,21,34]
fibs!!10            -- 55
```

We have to understand some functions and operators to interpret the code above.

- the `:` operator prepends an element to a list
- `tail` function returns a list without its first element
- `zipWith` uses a specified function (in this case `addition`) to combine corresponding elements of two lists (in this case `fibs` and `tail fibs`) to produce a third
- `take` returns a sized prefix of a list
- `!!` is the list index (subscript) operator, starting from 0

Another nice example is a definition for an infinite list of integers (starting at 2) where each number is not divisible by any previous number in the list.

```haskell
:{
primes = filterPrime [2..]
  where filterPrime (p:xs) =
          p : filterPrime [x | x <- xs, x `mod` p /= 0]
:}
take 10 primes      -- [2,3,5,7,11,13,17,19,23,29]
```

Due to high-level nature of the functional style, programs written in Haskell are often much more **concise** than in others languages. The language syntax was designed with concise programs in mind.

These are the main concepts for now. To start testing and learning, let’s get our hands dirty.

## The Haskell platform

A Haskell distribution may includes tools like:

- the Glasgow Haskell Compiler
- the Cabal build system
- the Stack tool
- core & widely-used packages

Glasgow Haskell Compiler (GHC) is an open source compiler and interactive environment (aka GHCi) for the language Haskell.

Let's see some concepts from the *Cabal build system*.

`CABAL` (the spec) is the Common Architecture for Building Applications & Libraries. It’s a specification for defining how Haskell applications and libraries should be built, defining dependencies, etc.

`.cabal` (the file format) is used to write down the definitions for a specific package.

```
library
  exposed-modules:     HelloWorld
  -- other-modules:
  -- other-extensions:
  build-depends:       base >= 4.11 && <4.12
  hs-source-dirs:      src
  default-language:    Haskell2010
```

The `Cabal library` implements the above specification and file format.

The cabal executable (`cabal-install`), is a command-line tool that uses Cabal (the library) to resolve dependencies and build packages.

What about **Stack**?

Stack is a replacement for `cabal-install`, i.e. the cabal executable. It is a build tool that works on top of the Cabal build system, with a focus on reproducible build plans and multi-package projects.

We can also count on online package repositories to complement the build system:

The [Hackage package repository](https://hackage.haskell.org/), providing more than ten thousand open source libraries and applications to help you get your work done

The [Stackage package collection](https://www.stackage.org/), a curated set of packages from Hackage which are regularly tested for compatibility. Stack defaults to using Stackage package sets to avoid dependency problems.

## Starting with Stack

In my computer I have the `brew` tool installed (a package manager for macOS and Linux)

With a simple command I was able to download and install the mentioned tools to start with Haskell.

```
$ brew install haskell-stack
...
🍺  /usr/local/Cellar/haskell-stack/2.3.3: 6 files, 55.4MB
```

A `stack` command starts our Haskell Interpreter.

```
$ stack ghci
...
Configuring GHCi with the following packages:
GHCi, version 8.8.3: https://www.haskell.org/ghc/  :? for help
Prelude>
```

`Prelude` is a module that contains a small set of standard definitions and is included automatically into all Haskell modules.

Let's do a simple test and quit.

```
Prelude> let x = 12 in x / 4
3.0
Prelude> :quit
Leaving GHCi.
```

## The first project

With Stack and a template we can generate a start project inside our current directory, but it suggest us to config some properties in advance. We can set these properties in the `~/.stack/config.yaml` file.

```
templates:
  params:
    author-name: Aldinei
    author-email: aldinei@gmail.com
    copyright: none
    github-username: pinei
    category: Development
```

We can use `stack new` to create our first Haskell project called `haskell-kitchen`.

You can access [stack-templates](https://github.com/commercialhaskell/stack-templates) to search for another template. Here the default "new-template" will be used.

```
$ stack new haskell-kitchen
Downloading template "new-template" to create project "haskell-kitchen" in haskell-kitchen/ ...
Looking for .cabal or package.yaml files to use to init the project.
Using cabal packages:
- haskell-kitchen/
...
Initialising configuration using resolver: lts-16.10
Total number of user packages considered: 1
Writing configuration to file: haskell-kitchen/stack.yaml
All done.
```

The `stack new` command should have created the following files:

```
├── app
│   └── Main.hs
├── ChangeLog.md
├── LICENSE
├── haskell-kitchen.cabal
├── package.yaml
├── README.md
├── Setup.hs
├── src
│   └── Lib.hs
├── stack.yaml
└── test
    └── Spec.hs
```

We can see some text files and source folders (`app`, `src` and `test`) containing `.hs` files.
 
The `package.yaml` is the preferred package format provided by Stack. The default behaviour is to generate the `.cabal` file from this `package.yaml`, so you should not modify the `.cabal` file. It is updated automatically as part of the stack build process.

The `Setup.hs` file is another component of the Cabal build system. It's technically not needed by Stack, but it is still considered good practice in the Haskell world to include it.

The project descriptor named `stack.yaml` gives our project-level settings.

In the `src\Lib.hs` source file, let's type a text in the function `someFunc` of the `Lib` module to see it printed to the output later.
 
```haskell
module Lib
    ( someFunc
    ) where

someFunc :: IO ()
someFunc = putStrLn "Welcome to Haskell Kitchen"
```

Let's see the `app\Main.hs` file:

```haskell
module Main where

import Lib

main :: IO ()
main = someFunc
```

The function named `main` in the module `Main` is special. It is defined to be the entry point of a Haskell program (similar to the main function in C), and must have an `IO type`, usually `IO ()`.

Our module `Lib` is imported here and the function `someFunc` will be invoked.

Now let's see the `test\Spec.hs` file.

```
main :: IO ()
main = putStrLn "Test suite not yet implemented"
```

It would be interesting to write some tests to learn and document some codes, but with this sample we haven't any clue about how to write the test cases. It's a subject for another article.

Let's use Stack to run our `hello-world` application. Type `stack build` to generate the binary ...

```
$ stack build
haskell-kitchen> configure (lib + exe)
Configuring haskell-kitchen-0.1.0.0...
haskell-kitchen> build (lib + exe)
Preprocessing library for haskell-kitchen-0.1.0.0..
Building library for haskell-kitchen-0.1.0.0..
Preprocessing executable 'haskell-kitchen-exe' for haskell-kitchen-0.1.0.0..
Building executable 'haskell-kitchen-exe' for haskell-kitchen-0.1.0.0..
[1 of 2] Compiling Main [Lib changed]
Linking .../haskell-kitchen-exe ...
haskell-kitchen> copy/register
Registering library for haskell-kitchen-0.1.0.0..
```

The binaries for the local platform (in my case x86_64-osx) are generated somewhere in the folder `.stack-work` under the project folder.

The command `stack exec` helps us to find the executable and run it ...

```
$ stack exec haskell-kitchen-exe
Welcome to Haskell Kitchen
```

The output is showing as expected. In a near future we can build a functional application.

For now let's test some code writing a new module in `src\Calculator.hs` for simple recursive functions.

```haskell
module Calculator
    ( double, sum, factorial, product
    ) where

double :: Num a => a -> a
double x = x + x

sum_list :: Num a => [a] -> a
sum_list[] = 0
sum_list(x:xs) = x + sum_list xs

product_list :: Num a => [a] -> a
product_list[] = 1
product_list(x:xs) = x * product_list xs

factorial :: Integral a => a -> a
factorial x = product_list [1..x]
```

We can try the functions using the GHCi environment. Execute `stack ghci` in the project folder.

```
$ stack ghci
Using main module: 1. Package `haskell-kitchen' component haskell-kitchen:exe:haskell-kitchen-exe with main-is file: ./haskell-kitchen/app/Main.hs
haskell-kitchen> configure (lib + exe)
Configuring haskell-kitchen-0.1.0.0...
haskell-kitchen> initial-build-steps (lib + exe)
Configuring GHCi with the following packages: haskell-kitchen
GHCi, version 8.8.3: https://www.haskell.org/ghc/  :? for help
[1 of 3] Compiling Calculator       ( ./haskell-kitchen/src/Calculator.hs, interpreted )
[2 of 3] Compiling Lib              ( ./haskell-kitchen/src/Lib.hs, interpreted )
[3 of 3] Compiling Main             ( ./haskell-kitchen/app/Main.hs, interpreted )
Ok, three modules loaded.
*Main Calculator Lib>
```

We now have 3 modules compiled and loaded, and we are able to invoke the functions from the `Calculator` module.

The `Prelude` module in the prompt gave way to a list of our loaded modules `Main Calculator Lib`. We can configure the prompt using `:set prompt "> "`.

```
*Main Calculator Lib> :set prompt "> "
> Calculator.double 3
6
> Calculator.sum [1..5]
15
> Calculator.product [2, 3]
6
> Calculator.factorial 5
120
> :quit
Leaving GHCi.
```

It seems our functions are working well, but we can make our project better with unit tests. I have to search for options before writing a second article in a series.