This is the second part of a hands-on guide on creating a Haskell based web service. No previous knowledge of haskell is required. However, basic understanding of RESTful web services is assumed. Other posts in this series: part 1, part 3.
2. Build and package a simple app using cabal
Introducing Cabal
Cabal (Common Architecture for Building Applications and Libraries) is a system for building and packaging Haskell libraries and programs. Think of it as Haskell’s equivalent of Python’s pip
, Node’s npm
and Scala’s sbt
.
Before we get started, make sure that you have cabal
installed and on the system path:
% cabal — version
cabal-install version 1.22.6.0
using version 1.22.4.0 of the Cabal library
Create a cabal app
Cabal makes it easy to build, package and test your application. It’s also straightforward to add dependencies on other libraries that cabal will fetch for you.
It is possible that different Haskell apps have dependencies on different versions of the same library. To prevent conflicts in your global Haskell environment, it’s a good idea to create a sandbox for your app. Cabal will then install the dependent libraries inside the sandbox.
% mkdir cabal-example
% cd cabal-example
% cabal sandbox init
Writing a default package environment file to
/Users/psingh/tmp/haskell/eac-articles/cabal
example/cabal.sandbox.config
Creating a new sandbox at
/Users/psingh/tmp/haskell/eac-articles/cabal-example/.cabal-sandbox
Now, we can initialise our app. The easiest way to create a cabal app is using the cabal init
command. Follow the prompts and cabal will generate the config file for you. Here’s an example interaction on my system:
% cabal init
Package name? [default: cabal-example]
Package version? [default: 0.1.0.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: Parambir Singh]
Maintainer email? [default: user@domain.com]
Project homepage URL?
Project synopsis?
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)]
What does the package build:
1) Library
2) Executable
Your choice? 2
What is the main module of the executable:
* 1) Main.hs (does not yet exist)
2) Main.lhs (does not yet exist)
3) Other (specify)
Your choice? [default: Main.hs (does not yet exist)] 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] n
Source directory:
* 1) (none)
2) src
3) Other (specify)
Your choice? [default: (none)] 1
Guessing dependencies…
Generating LICENSE…
Generating Setup.hs…
Generating cabal-example.cabal…
Warning: no synopsis given. You should edit the .cabal file and add
one.
You may want to edit the .cabal file and add a Description field.
You will now have a cabal-example.cabal
file in your source directory. Remember that we selected Main.hs
as our main module during the cabal init
process. Add a Main.hs
file now to the root of your source folder with the following content:
c2f c = (c * 9/5) + 32
main = do
print (c2f 37)
Running your cabal app (cabal run)
To run your app, use the cabal run
command:
% cabal run
Package has never been configured. Configuring with default flags. If this fails, please run configure manually.
Resolving dependencies…
Configuring cabal-example-0.1.0.0…
Preprocessing executable ‘cabal-example’ for cabal-example-0.1.0.0…
[1 of 1] Compiling Main ( Main.hs, dist/build/cabal-example/cabal-example-tmp/Main.o )
Linking dist/build/cabal-example/cabal-example …
Running cabal-example…
98.6
Other useful cabal commands
cabal clean
Removes the generated artifacts (executables etc.)
% cabal clean
cleaning…
cabal build
Compiles and links your source code to generate the executable.
% cabal build
Package has never been configured. Configuring with default flags. If this fails, please run configure manually.
Resolving dependencies…
Configuring cabal-example-0.1.0.0…
Building cabal-example-0.1.0.0…
Preprocessing executable ‘cabal-example’ for cabal-example-0.1.0.0…
[1 of 1] Compiling Main ( Main.hs, dist/build/cabal-example/cabal-example-tmp/Main.o )
Linking dist/build/cabal-example/cabal-example …
Run the generated executable:
% ./dist/build/cabal-example/cabal-example
98.6
cabal install
Installs the generated artifact into the cabal sandbox. This is somewhat similar to mvn install
in Java world.
% cabal install
Resolving dependencies…
Notice: installing into a sandbox located at
/Users/psingh/tmp/haskell/eac-articles/cabal-example/.cabal-sandbox
Configuring cabal-example-0.1.0.0…
Building cabal-example-0.1.0.0…
Installed cabal-example-0.1.0.0
cabal repl
Starts a ghci
session for your project (i.e. with your modules loaded). You can easily test your functions here.
% cabal repl
Preprocessing executable ‘cabal-example’ for cabal-example-0.1.0.0…
GHCi, version 7.10.2: http://www.haskell.org/ghc/ :? for help
[1 of 1] Compiling Main ( Main.hs, interpreted )
Ok, modules loaded: Main.
*Main> c2f 37 — call the c2f function defined in our Main.hs file
98.6
*Main> main — yes, this is the main function we defined in Main.hs
98.6
*Main>
cabal update
Downloads the latest package list for cabal. It’s useful to run cabal update
before running cabal init
or cabal install
to make sure that cabal has knowledge about the latest packages
% cabal update
Downloading the latest package list from hackage.haskell.org
Source
The complete source for this section is available on github
Next…
In Part 3, We’ll write a simple web app using the Scotty web framework for Haskell.
Top comments (0)