Getting Started with
Nov. 19th, 2013
Software Development as of 2013
● Programming language implementation’s version and runtime management
○ rbenv / rvm
○ pythonbrew / virtualenv
○ cabal cover this one with sandbox as of 1.18. Before that, it is cabal-dev
○ N.A. for dynamic type PL
○ cabal do all of the dependencies resolving, could be parallel built with “-j” now. For more
complex project, use Shake
○ bulding large ghc project is slow. Go is fast but its trade-off is rich type system.
○ Unit Test. → dynamic type (especially weak type) heavily rely on it, because no type
checking. All is postponed until runtime.
○ Continous Integration (Test) → All needed
○ Depending on your deployment settings. But for compiled language, it’s just a binary.
There are differences between static type and dynamic type PL, but the main flow is basically the same.
Software Development as .. (cont.)
● Coding Convention
○ If a language’s type information is clear enough, basically the convention could be
suggested by any lint program. Otherwise, it is provided by static analysis, and its difficulty
largely depends on the language itself. Haskell has hlint, and it’s good
● Code Review
○ Any good reviewing system applied.
● Version Control System
○ The same.
○ pre-commit hook to remove spaces at the end of line
○ IDE could provide smart auto-completion inferenced from type information, which is not
what a vim/emacs could be compared. Editors mostly just do simple text/pattern matching.
○ But FP Complete costs you some money. Leksah might be considered.
Haskell Center Community edition (free) just released yesterday
● Although haskell-platform is convenient for new comers, my opinion is to install it from official
binaries and stick to sandboxed build for each project.
● System-wide intallation is easy to result in conflicts after updating package info.
● Individual installation also make you easier to test-build for each version of ghc
cabal -- haskell building system
● Keep your cabal as new as possible, this is also another reason not to use haskell-platform,
some bug fix might not be updated timely.
● Don’t use the .cabal generated by “cabal init”. The default is 1.10, but I prefer version >= 1.16.
Because I stepped on obvious bug before and it’s fixed in 1.16: https://github.
● From 1.18, you no longer have to use cabal-dev for sandboxed-build. A new feature called
“cabal sandbox” was released.
● Reference (Cabal User Guide): http://www.haskell.org/cabal/users-guide/installing-packages.
● For existing project with a .cabal file, do the following. (You still need to “cabal init” to generate .
cabal if you don’t have one
● build with different version of ghc http://asciinema.org/a/6446?speed=4
cabal install --only-dependencies --enable-tests
cabal configure --enable-tests
cabal build && cabal test
● Personally, I would also like to switch on cabal’s test running feature
● switching on useful flags
● -Wall : warning for details
● -fwarn-tabs: one of bad things
of haskell is indent-sensitive.
Like programming in Python,
space indentation is
recommended, and I tend to
make compiler warns about
● -O2: ghc could do very
aggressive optimization when
the flags was set.
● -funbox-strict-fields: Most type
in ghc is boxed. a “Int” is
composed of two words on the
heap. This flag would help you
unbox type like “!Int”
● It is kind of a mess for the
current status of Hackage.
There are very unreliable
packages uploaded. And some
of them write their version
● Michael Snoyman proposed
stackage (Stable hacakge) for
hosting packages stable
● Before the issue is resolved
completely, I prefer to write
package version more strictly.
● >= latest minor version & <
latest minor version + 0.2
Kind of like the relationship between dpkg and apt-get
cabal as an adapter for ghc-pkg
cabal -v sandbox hc-pkg find-module "Data.Csv"
cabal -v sandbox hc-pkg list "http*"
● list packages starting with “http” in its name in the current sandbox
cabal -v sandbox hc-pkg dot
● find out which package the “Data.Csv” come from
● generate a dot file describing package dependencies
● Type checking eliminate certain type of bugs, but not all of them.
● Tools/Libraries exist to hunt other types of bugs
● QuickCheck: For pure functions that is complex enough, so that it is not possible to be described
by Haskell’s type system.
● HUnit: For traditional unit test. Usually functions with side effects. And small enough to be a unit.
● HSpec: From Ruby’s RSpec, if you like behavior driven test. Some projects like mighttpd2 and
warp-related using it. ← wouldn’t talk about it since I’ve never used it.
● A famous example commonly show up in tutorial is “whether two int lists are reverse of each
other”, the type we can write down at best is “[Int] -> [Int] -> Bool” , unable to type-check if it a list
is a reverse of the other.
The program would use random sequence generator to generate test input and see if the
● Ref: https://www.fpcomplete.com/user/pbv/an-introduction-to-quickcheck-testing
● Not very different from xUnit
● Could be used to test for operation involving side-effects. Like reading config files, connection
● Most CI service platform provide Haskell supports
○ travis-ci: with .travis.yml
○ drone.io: never used it
● Jenkins is possible, but never used it before. I think Yesod is using it as CI
● Ref: http://about.travis-ci.org/docs/user/languages/haskell/
Hoogle (for function search)
● unlike other mainstream languages, Haskell have rich information about types that search
engine could be used for.
● You have a certain function in mind, you knows its input and output, but not sure about whether
somebody have written it before. Query it by type.
● Googling the package name and
check-out the number of reverse
dependencies to see if it is a
● As in the food court, looking for
Looking up the diff
between different versions
of package http://hdiff.
My Picks of Libraries
● command line
● Lib to solve the problem of lazy IO
● low-level http handling
Haskell community still lacks a website like https://www.ruby-toolbox.com/
Here is my picks for reference.
● web framework
● string builder
Rule of thumbs for new comers
● Don’t use String. For unicode, use Text. For ascii, use ByteString
● Read the problem of Lazy IO: http://stackoverflow.com/questions/5892653/whats-so-bad-about-
For most cases, there shouldn’t be a problem. But when you need to open many
files/connections. Consult anyone who is familiar with this topic.
● hlint as much as you can
● Try to heap overflow a program by yourself:
● Use undefined for your convenience. (undefined in Haskell is bottom, could be a drop-in
replacement for any implementation)
Commonly Used Ghc Extension
● Haskell comittee only put a feature into standard when there is a consensus, other experimental
things are only switched on when specified with Extension syntax.
Any of double quoted strings are default to be the type String, using this extension make it could be
any type belonging the typeclass IsString, ByteString particularly
Indicate an argument of a function should be evaluated to a certain degree. (Metaphor: the outer
most box is opened.)
Typeclass could be multiple polymorphic params. The Haskell98 doesn’t allow this.
The type variable written in “where” part become free variable, but not bind to type variable of the
FP Complete has an introduction series about ghc’s extensions
● One of caveat debugging Haskell is it doesn’t have a guaranteed execution sequence once your
code is pure. Most of debugging techniques you learned from imperative language barely apply.
● Debug.trace: could print something, but the sequence is not guranteed
● Make code to be in IO Monad, and use print.
● Read Core, which is the assemly language of ghc implementation. But most of time it is not for
logic error, but to trace for memory leak.