Haskell: Batteries Included

Duncan Coutts, Isaac Potoczny-Jones and I have just finished a short proposal for this year’s Haskell Symposium for a standard library platform for Haskell. Beyond just the core libraries, this would provide a complete, stable base for the majority of Haskell development, and a straightforward task for distros to support Haskell – just provide the Haskell Platform.

The platform well and truly subsumes the current core and extra libraries, and provide all the other nice libraries from Hackage, for networking, databases, data and control structures, guis, XML, graphics and so on. Haskell with batteries included, on every machine.

The plan is to have this all in place by the Haskell Symposium, so the main challenge is to automate the production of the library quality assurance. By September we hope to have at least one or two distros fully supporting the platform (there are already tools to generate distro native packages for at Arch, Gentoo, Fedora and Debian, so that task is easy). Who knows, with any luck we may see Haskell on a few distros, out of the box.

What do you think? Is the idea of a stable, comprehensive library suite for Haskell, widely available, an attractive proposition as a developer?

On a related note, if you’re a developer interested in FP, you might consider attending the Developer Tracks on Functional Programming, alongside the Commercial Users of FP workshop at ICFP this year, in Vancouver. Lots of practical talks on Haskell and Erlang for building commerical systems.

The lambda revolution

This article describes the entire process of writing, packaging and releasing a new Haskell library. If you love programming Haskell, and want to keep doing so, you’ll write some libraries and release them. The lambda revolution isn’t going to happen without your code!

Creating Data.DList, it took about 60 minutes. People often need O(1) append, so about time we had a library for it. Here’s the entire transcript of creating a new Haskell project and releasing it to a public server. I then created a web page for the project, and announced it on the haskell@ mailing list. I used the following tools:

Ready? Here we go!


Script started on Mon Dec 11 13:47:40 2006

$ cd dons/src
$ mkdir dlist
$ cd dlist

$ mkcabal
Project name: dlist
What license ["GPL","LGPL","BSD3","BSD4","PublicDomain","AllRightsReserved"] ["BSD3"]:
What kind of project [Executable,Library] [Executable]: Library
Is this your name? - "Don Stewart " [Y/n]:
Is this your email address? - "<dons@cse.unsw.edu.au>" [Y/n]:
Created Setup.lhs and dlist.cabal

$ cp ~/dons/src/yi/Yi/Lexers.hs .
$ ls
Lexers.hs   Setup.lhs   dlist.cabal

$ mkdir Data
$ mv Lexers.hs Data/DList.hs

$ vim Data/DList.hs
$ vim dlist.cabal

$ darcs init
$ darcs add dlist.cabal Setup.lhs Data/ Data/DList.hs
$ darcs record --all
Shall I record this change? (1/?)  [ynWsfqadjkc], or ? for help: a
What is the patch name? Initial import of dlist package
Do you want to add a long comment? [yn]n
Finished recording patch 'Initial import of dlist package'

$ runhaskell Setup.lhs configure --prefix=/home/dons
Setup: Warning: No exposed modules or executables in this package.
Setup: Error: Non-empty library, but empty exposed modules list. 
Cabal may not build this library correctly

$ vim dlist.cabal

$ runhaskell Setup.lhs configure --prefix=/home/dons
Configuring dlist-0.1...
configure: /home/dons/bin/ghc-pkg
configure: Dependency base-any: using base-2.0
configure: Using install prefix: /home/dons
configure: Binaries installed in: /home/dons/bin
configure: Libraries installed in: /home/dons/lib/dlist-0.1/ghc-6.6
configure: Private binaries installed in: /home/dons/libexec
configure: Data files installed in: /home/dons/share/dlist-0.1
configure: Using compiler: /home/dons/bin/ghc
configure: Compiler flavor: GHC
configure: Compiler version: 6.6
configure: Using package tool: /home/dons/bin/ghc-pkg
configure: Using ar found on system at: /usr/bin/ar
configure: Using haddock found on system at: /home/dons/bin/haddock
configure: No pfesetup found
configure: Using ranlib found on system at: /usr/bin/ranlib
configure: Using runghc found on system at: /home/dons/bin/runghc
configure: Using runhugs found on system at: /home/dons/bin/runhugs
configure: Using happy: /home/dons/bin/happy
configure: Using alex: /home/dons/bin/alex
configure: Using hsc2hs: /home/dons/bin/hsc2hs
configure: No c2hs found
configure: Using cpphs: /home/dons/bin/cpphs
configure: No greencard found
Preprocessing library dlist-0.1...
Building dlist-0.1...

$ runhaskell Setup.lhs build
Preprocessing library dlist-0.1...
Building dlist-0.1...
Data/DList.hs:17:2: parse error on input `DList'

$ vim Data/DList.hs +17

$ runhaskell Setup.lhs build
Preprocessing library dlist-0.1...
Building dlist-0.1...
[1 of 1] Compiling Data.DList       ( Data/DList.hs, /usr/obj/cabal/Data/DList.o )
/usr/bin/ar: creating /usr/obj/cabal/libHSdlist-0.1.a

$ runhaskell Setup.lhs install
Installing: /home/dons/lib/dlist-0.1/ghc-6.6 & /home/dons/bin dlist-0.1...
Registering dlist-0.1...
Reading package info from ".installed-pkg-config" ... done.
Saving old package config file... done.
Writing new package config file... done.

$ darcs amend-record
Mon Dec 11 14:20:56 EST 2006  Don Stewart <dons@cse.unsw.edu.au>
  * Initial import of dlist package
Shall I amend this patch? [yNvpq], or ? for help: y
hunk ./Data/DList.hs 15
-module Data.DList
+module Data.DList (
Shall I add this change? (1/?)  [ynWsfqadjkc], or ? for help: y
hunk ./dlist.cabal 10
+Exposed-modules:     Data.DList
Shall I add this change? (2/?)  [ynWsfqadjkc], or ? for help: y
Finished amending patch:
Mon Dec 11 14:21:53 EST 2006  Don Stewart <dons@cse.unsw.edu.au>
  * Initial import of dlist package

$ runhaskell Setup.lhs haddock
Preprocessing library dlist-0.1...
Running Haddock for dlist-0.1...
Warning: cannot use package base-2.0:
   HTML directory /home/dons/share/ghc-6.6/html/libraries/base does not exist.
/usr/obj/cabal/tmp/Data/DList.hs:"/usr/obj/cabal/tmp/Data/DList.hs": 37:1: parse error in doc string: [TokPara]

$ vim Data/DList.hs +37

$ runhaskell Setup.lhs haddock
Preprocessing library dlist-0.1...
Running Haddock for dlist-0.1...
Warning: cannot use package base-2.0:
   HTML directory /home/dons/share/ghc-6.6/html/libraries/base does not exist.

$ w3m -dump dist/doc/html/index.html 
 dlist-0.1:  Contents Index
dlist-0.1:
Differences lists: lists supporting efficient append
Modules
show/hideData
Data.DList
Produced by Haddock version 0.8

$ mkdir tests
$ vim tests/Properties.hs
$ vim tests/Parallel.hs

$ cd tests
$ runhaskell Properties.hs 
2: singleton                : OK, 1000 tests.
1: model                    : OK, 1000 tests.
2: snoc                     : OK, 1000 tests.
1: append                   : OK, 1000 tests.
$ cd ..

$ darcs add tests
$ darcs add tests/Parallel.hs tests/Properties.hs
$ darcs whatsnew -s
M ./Data/DList.hs -1 +1
A ./tests/
A ./tests/Parallel.hs
A ./tests/Properties.hs

$ darcs record --all
...
Shall I record this change? (6/?)  [ynWsfqadjkc], or ? for help: y
What is the patch name? Add QuickChecks
Finished recording patch 'Add QuickChecks'

$ darcs setpref test "cd tests ; runhaskell Properties.hs"
Changing value of test from '' to 'cd tests ; runhaskell Properties.hs'
changepref test
cd tests ; runhaskell Properties.hs
Shall I record this change? (1/?)  [ynWsfqadjkc], or ? for help: y
What is the patch name? pre   run tests on each commit
Do you want to add a long comment? [yn]n
Running test...
2: singleton                : OK, 1000 tests.
2: snoc                     : OK, 1000 tests.
1: model                    : OK, 1000 tests.
2: append                   : OK, 1000 tests.
Test ran successfully.
Looks like a good patch.
Finished recording patch 'run tests on each commit'

$ darcs whatsnew -s
No changes!

$ darcs tag
What is the version name? 0.1   dlist 0.1
Finished tagging patch 'TAG dlist 0.1'

$ runhaskell Setup.lhs sdist
Building source dist for dlist-0.1...
*** Exception: LICENSE: copyFile: does not exist (No such file or directory)

$ cp ~/pqc/LICENSE .
$ vim LICENSE 

$ darcs add LICENSE
$ darcs record
addfile ./LICENSE
Shall I record this change? (1/?)  [ynWsfqadjkc], or ? for help: y
...
Shall I record this change? (2/?)  [ynWsfqadjkc], or ? for help: y
What is the patch name? add license
Do you want to add a long comment? [yn]n
Running test...
2: singleton                : OK, 1000 tests.
2: snoc                     : OK, 1000 tests.
1: model                    : OK, 1000 tests.
2: append                   : OK, 1000 tests.
Test ran successfully.
Looks like a good patch.
Finished recording patch 'add license'

$ vim README
$ darcs add README
$ darcs record --all
What is the patch name? Add a readme
Do you want to add a long comment? [yn]n
Running test...
2: singleton                : OK, 1000 tests.
2: snoc                     : OK, 1000 tests.
1: model                    : OK, 1000 tests.
2: append                   : OK, 1000 tests.
Test ran successfully.
Looks like a good patch.
Finished recording patch 'Add a readme'

$ ls
Data        LICENSE     README      Setup.lhs   _darcs      dist        dlist.cabal tests

$ darcs dist -d dlist-0.1. 
Created dist as dlist-0.1.tar.gz

$ darcs whatsnew -s
No changes!

$ darcs put pill00.cse.unsw.edu.au:/home/chakcvs/darcs/dlist/
Finished applying...

Script done on Mon Dec 11 15:04:54 2006