When learning a programming language, building a package should be considered equivalent to emancipation.

This is because only by creating small reusable components one can eventually build larger complicated systems. And packages are the unit for this. So building your own package, putting it on a package repository for your language and iterating over it is pretty much a baseline for any language you work with.

So here I am, ready to leave the world of loading files into the Haskell REPL and starting to load packaged modules instead.

This post is specifically about moving the functions I created to generate prime numbers for Project Euler problems into a separate package where they can be referred to from other places. So I started by moving the file in question (`Problem007.hs`

) into a separate directory, I gitified it and made it available on github. The file was also renamed to `Euler.hs`

as that will be the entry point for the library.

So I currently have in `~/dev/euler`

one file — `Euler.hs`

. Let’s start then:

`cabal init`

`cabal init`

is super detailed in all the questions it asks:

```
Package name? [default: euler]
Package version? [default: 0.1.0.0] 0.1.0
Please choose a license:
* 1) (none)
2) GPL-2
3) GPL-3
4) LGPL-2.1
5) LGPL-3
6) AGPL-3
7) BSD2
8) BSD3
9) MIT
10) ISC
11) MPL-2.0
12) Apache-2.0
13) PublicDomain
14) AllRightsReserved
15) Other (specify)
Your choice? [default: (none)] 9
Author name? [default: Luis] Luis Rodrigues Soares
Maintainer email? [default: luis@decomputed.com]
Project homepage URL? https://github.com/decomputed/euler
Project synopsis? Mathematics utilities for Haskell
Project category:
* 1) (none)
2) Codec
3) Concurrency
4) Control
5) Data
6) Database
7) Development
8) Distribution
9) Game
10) Graphics
11) Language
12) Math
13) Network
14) Sound
15) System
16) Testing
17) Text
18) Web
19) Other (specify)
Your choice? [default: (none)] 12
What does the package build:
1) Library
2) Executable
Your choice? 1
What base language is the package written in:
* 1) Haskell2010
2) Haskell98
3) Other (specify)
Your choice? [default: Haskell2010] 1
Include documentation on what each field means (y/n)? [default: n] y
Source directory:
* 1) (none)
2) src
3) Other (specify)
Your choice? [default: (none)] 2
Guessing dependencies...
Generating LICENSE...
Warning: LICENSE already exists, backing up old version in LICENSE.save0
Generating Setup.hs...
Generating euler.cabal...
You may want to edit the .cabal file and add a Description field.
```

And after it runs, I now have the following in my project’s directory:

```
drwxr-xr-x 8 luis luis 4096 Feb 21 11:04 .git/
-rw-r--r-- 1 luis luis 107 Feb 21 10:53 .gitignore
-rw-r--r-- 1 luis luis 1065 Feb 21 11:01 LICENSE
-rw-r--r-- 1 luis luis 170 Feb 21 10:56 README.md
-rw-r--r-- 1 luis luis 46 Feb 21 11:01 Setup.hs
-rw-r--r-- 1 luis luis 2053 Feb 21 11:01 euler.cabal
drwxr-xr-x 2 luis luis 4096 Feb 21 11:03 src/
```

Note that I moved `Euler.hs`

into `src/`

. Also, there is one thing we should guarantee here: that `euler.cabal`

contains a reference to module `Euler`

in the `exposed-modules`

section, like so:

```
exposed-modules: Euler
```

So with that in place, we can now do `cabal configure`

:

```
Resolving dependencies...
Configuring euler-0.1.0...
```

and then `cabal build`

:

```
Building euler-0.1.0...
Preprocessing library euler-0.1.0...
[1 of 1] Compiling Euler ( src/Euler.hs, dist/build/Euler.o )
In-place registering euler-0.1.0...
```

If after this we do `cabal clean`

we’ll clean the whole thing up.

So the project is now cabalized. Our next step is to put it into Hackage. Let’s run `cabal configure`

and `cabal build`

again and after this we prepare our package with `cabal sdist`

:

```
Distribution quality warnings:
No 'description' field.
When distributing packages it is encouraged to specify source control
information in the .cabal file using one or more 'source-repository' sections.
See the Cabal user guide for details.
Building source dist for euler-0.1.0...
Preprocessing library euler-0.1.0...
Source tarball created: dist/euler-0.1.0.tar.gz
```

So there’s some fields we forgot to fill in but since these are only warnings let’s silently ignore them. We have our `tar.gz`

file and now we should head over to Hackage, create an account and then upload our `tar.gz`

; after this our package is now in Hackage.

So now let’s see if that really works.

Open another terminal, in some `test`

directory, and let’s do:

`cabal update`

`cabal install euler`

which should succeed with:

```
Resolving dependencies...
Downloading euler-0.1.0...
Configuring euler-0.1.0...
Building euler-0.1.0...
Installed euler-0.1.0
```

if now we fire up `ghci`

and try our package:

```
GHCi, version 7.8.4: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> :module +Euler
Prelude Euler> trialAndDivision 50
Loading package euler-0.1.0 ... linking ... done.
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47]
```

And there we have it! What’s left to do?

- Adding the rest of fields missing in
`euler.cabal`

; - There’s a warning about global spacenames when I uploaded the file, have to find out what this is;
- Add tests;
- Add linting;
- Add documentation.

But even without those in place, we now have a workflow to create Haskell packages and push them over to Hackage, so that they can be used by others.

:-)