learnhaskell/README.md
Leif Warner 093e9f1c65 s/su -c/sudo
I believe most people use sudo for this sort of thing, rather than su + root password.
2015-01-04 20:59:45 -08:00

25 KiB

This is my recommended path for learning Haskell.

Something to keep in mind: don't sweat the stuff you don't understand immediately. Just keep moving.

Community

Our IRC channel is #haskell-beginners on Freenode.

IRC web client here: http://webchat.freenode.net/

Community Guidelines

Letter to a Young Haskell Enthusiast

Be nice above all else!

Primary course

What are Haskell, GHC, and Cabal?

Haskell is a programming language as laid out in the reports, most recent one being in 2010. http://www.haskell.org/onlinereport/haskell2010/

GHC is the most popular compiler for Haskell and is what you'll install along with Cabal. Cabal is the project and dependency management tool used with GHC. You almost definitely want both if you're going to start writing Haskell.

Cabal is equivalent to Ruby's Bundler, Python's pip, Node's NPM, Maven, etc. GHC manages packaging itself, Cabal chooses what versions to install.

Getting started

Ubuntu

This PPA is excellent and is what I use on all my Linux dev and build machines: http://launchpad.net/~hvr/+archive/ghc

Specifically:

  • sudo apt-get update
  • 12.04 and below -> sudo apt-get install python-software-properties
  • 12.10 and above -> sudo apt-get install software-properties-common
  • sudo add-apt-repository -y ppa:hvr/ghc
  • sudo apt-get update
  • sudo apt-get install cabal-install-1.20 ghc-7.8.3 happy-1.19.4 alex-3.1.3

Then add ~/.cabal/bin:/opt/cabal/1.20/bin:/opt/ghc/7.8.3/bin:/opt/happy/1.19.4/bin:/opt/alex/3.1.3/bin to your PATH (bash_profile, zshrc, bashrc, etc)

Optional You could also add .cabal-sandbox/bin to your path. Code that you are actively developing will be available to you from the command line. This only works when your current working directory is a cabal sandbox.

Debian

GHC Repository for debian stable

If you use Debian stable, it is easier to use http://deb.haskell.org/. To use this:

  • Add the line deb http://deb.haskell.org/stable/ ./ to /etc/apt/sources.list
  • run sudo apt-get update
  • run sudo apt-get install ghc-7.8.3 happy alex cabal-install

Using Ubuntu PPA

If you're not using stable, you can follow the same steps as Ubuntu, but has to execute an additional command. Immediately after sudo add-apt-repository -y ppa:hvr/ghc is ran, run:

  • sudo sed -i s/jessie/trusty/g /etc/apt/sources.list.d/hvr-ghc-jessie.list

For other Debian versions, just replace all occurences of "jessie" with your version name in the command above.

If, for some reason, the file /etc/apt/sources.list.d/hvr-ghc-jessie.list does not exist, then /etc/apt/sources.list should contain a line like this:

deb http://ppa.launchpad.net/hvr/ghc/ubuntu jessie main

Replace "jessie" with "trusty" in this line.

Manual compilation

You can follow the guide written for Mac OS X: http://www.davesquared.net/2014/05/platformless-haskell.html. Notes:

  • set your prefix accordingly when configuring ghc
  • instead of grabbing the cabal-install binary, grab the source and then run bootstrap.sh script.

Fedora 20

To install Haskell 7.8x from the unofficial repo (Fedora 21+ will include it in the official one:

Arch Linux

To install Haskell from the official repos on Arch Linux, run

sudo pacman -S cabal-install ghc happy alex haddock

Gentoo

On Gentoo, you can install the individual components of the Haskell Platform through Portage. If you use ACCEPT_KEYWORDS=arch (as opposed to ACCEPT_KEYWORDS=~arch), Portage will install ancient versions of the various Haskell things. With that in mind, iff you use ACCEPT_KEYWORDS=arch, add the following to /etc/portage/package.keywords.

dev-haskell/cabal-install
dev-lang/ghc

Once that is done,

emerge -jav dev-lang/ghc dev-haskell/cabal-install

Gentoo keeps a "stable" (read: old) version of cabal-install in the Portage tree, so you'll want to use cabal-install to install the more recent version. Note that the backslashes are intentional.

\cabal update
\cabal install cabal-install

You have now installed cabal on a global scale with portage, and locally in your home directory with cabal-install. The next step is to make sure that when you run cabal in a terminal, your shell will run the up-to-date version in your home directory. You will want to add the following lines to your shell's configuration file:

PATH=$PATH:$HOME/.cabal/bin
alias cabal="$HOME/.cabal/bin/cabal"

If you don't know what your shell is, more than likely, your shell is Bash. If you use Bash, the file you will edit is ~/.bashrc. If you use Z-shell, the file is ~/.zshrc. You can run the following command to find out what your shell is.

< /etc/passwd grep $(whoami) | awk -F/ '{print $NF}'

I use zsh, so that command outputs zsh when I run it.

Once you do all of that, you'll want to install the additional tools alex and happy.

cabal install alex happy

Congratulations! You now have a working Haskell installation!

Mac OS X

10.9

Install the GHC for Mac OS X app, which includes GHC and Cabal. It provides instructions on how to add GHC and Cabal to your path after you've dropped the .app somewhere.

10.6-10.8

Do the binary distribution install described below with this tarball:

Windows

Don't forget to run the installer as administrator as it will want to install in your Program Files.

Other Linux users

Download the latest binary distributions for cabal and ghc:

GHC

GHC is the most popular way to work in the Haskell language. It includes a compiler, REPL (interpreter), package management, and other things besides.

Cabal

Cabal does project management and dependency resolution. It's how you'll install projects, typically into their own sandbox.

Detailed manual install guide for Mac OS X

You don't need this if you use the .app, but if it doesn't work for you, try this with the binary distribution.


Yorgey course - Do this first, this is the primary way I recommend being introduced to Haskell.

http://www.seas.upenn.edu/~cis194/spring13/index.html Brent Yorgey's course is the best I've found so far and replaces both Yann Esposito's HF&H. This course is valuable as it will not only equip you to write basic Haskell but also help you to understand parser combinators.

The only reason you shouldn't start with cis194 is if you are not a programmer or are an inexperienced one. If that's the case, start with http://learnyouahaskell.com/ and transition to cis194.

If you are not new to programming, Learn You A Haskell and http://book.realworldhaskell.org/ are recommended primarily as supplemental references for completing the cis194 course. RWH has some additional material that LYAH does not that is useful to people using Haskell in production as well.


Supplementary course that provides more material on intermediate topics

This is Bryan O'Sullivan's online course from the class he teaches at Stanford. If you don't know who he is, take a gander at half the libraries any Haskell application ends up needing and his name is on it. Of particular note if you've already done the Yorgey course are the modules on phantom types, information flow control, language extensions, concurrency, pipes, and lenses.

Exercises for practice (do this after cis194)

You should do Yorgey's course before attempting this: https://github.com/NICTA/course/

Secondary material, references

Learn You a Haskell for Great Good (LYAH) and Real World Haskell (Thanks bos!) are available online.

I recommend RWH as a reference (thick book). The chapters for parsing and monads are great for getting a sense for where monads are useful. Other people have said that they've liked it a lot. Perhaps a good follow-up for practical idioms after you've got the essentials of Haskell down?

For understanding list and fold

For learning some common typeclasses

Useful for understanding Functor, Applicative, Monad, Monoid and other typeclasses in general but also some Hask-specific category theory:

Understanding basic Haskell error messages

Development Environment

Emacs

Vim

Sublime Text

FAQ and working with Cabal

Fantastic FAQ

In addition to being an amazing guide for all kinds of things such as GADTs, this also covers some useful basics for Cabal

Cabal guidelines

Cabal Hell was a problem for Haskell users before the introduction of sandboxes. Installing outside of a sandbox will install into your user package-db. This is not a good idea except for foundational packages like Cabal, alex, and happy. Nothing else should be installed in the user or global package-dbs unless you know what you're doing.

To experiment with a package or start a project, begin by doing cabal sandbox init in a new directory.

Put briefly:

  • Always use sandboxes for installing new packages, building new or existing projects, or starting experiments
  • Use cabal repl to start a project-scoped ghci instance

The sandbox-based approach I suggest should avoid package-dependency problems, but it's incompatible with the way the Haskell Platform provides pre-built packages. If you're still learning Haskell and don't understand how ghc-pkg and Cabal work, avoid Platform and instead use the install instructions earlier in the guide.

Search code by type signature

The Hoogle search engine can search by type:

http://www.haskell.org/hoogle/?hoogle=%28a+-%3E+b%29+-%3E+%5ba%5d+-%3E+%5bb%5d

Alternately:

https://www.fpcomplete.com/hoogle

Also Hayoo (which has all of hackage enabled for search by default): http://holumbus.fh-wedel.de/hayoo/hayoo.html

Setting up your own local instance of Hoogle

https://gist.github.com/bitemyapp/3e6a015760775e0679bf

Haddock

Note that these posts are slightly out of date: for example, now Hackage sports shiny new info with documentation info and build status.

What you really need to know

In order to have haddocks include documentation for related packages, you have to set documentation: True in your ~/.cabal/config. If it was left on the default (False) or set to False, you'll have to delete all your packages and reinstall before generating haddocks.

The other thing to keep in mind is that due to the way the $pkg parameter gets interpolated by cabal, not by you, the html-location and content-location parameters must be in single quotes and entered into a shell or contained in a shell script. They will not work in a Makefile, because it will think they are Make variables!

#!/usr/bin/env sh

cabal haddock --hoogle --hyperlink-source --html-location='http://hackage.haskell.org/package/$pkg/docs' --contents-location='http://hackage.haskell.org/package/$pkg'

What does that <- / do / list comprehension syntax sugar do?

TravisCI

If you're as big a fan of TravisCI as I am, then I strongly recommend you look at using https://github.com/hvr/multi-ghc-travis as the basis of the travis.yml for your Haskell projects.

Fun Stuff

After you're comfortable with Haskell, strongly consider learning Lenses and Prisms, even if just as a "user". You don't need to understand the underlying category for it to be useful.

Seen here: http://hackage.haskell.org/package/lens

Frontend/JavaScript

We have an embarrassment of riches! There are three main choices I would recommend:

Which frontend language do I use?

GHCJS and Haste are both fully Haskell. GHCJS will work with more Haskell packages than Haste, but this doesn't affect a lot of frontend projects. PureScript isn't Haskell at all, so direct code sharing with your backend will not work.

GHCJS has the fattest runtime payload overhead at about 100kb (luite is working on this). Haste and PureScript are competitive.

PureScript has the best JS tooling integration (uses gulp/grunt/bower), GHCJS and Haste integrate better with Haskell's tooling (Cabal).

All three are great choices and will work for most frontend projects.

Parsing in Haskell

Parsing and generating JSON

Laziness, strictness, guarded recursion

For a more thorough understanding of laziness, NF, WHNF

Brief demonstration

let a = 1 : a -- guarded recursion, (:) is lazy and can be pattern matched.
let (v : _) = a
> v
1
> head a -- head a == v
1

let a = 1 * a -- not guarded, (*) is strict
> a
*** Exception: <<loop>>

Parallelism/Concurrency

Lenses and Prisms

People vastly overestimate the difficulty of using Lens. Anybody comfortable with Functor/Foldable/Traversable (or even just the first one) can leverage lenses and prisms to make their life happier.

If you've ever done something like: (fmap . fmap) you were "lensing" in your head.

I recommend these two tutorials/introductions:

Monads and monad transformers

Do not do these until you understand typeclasses, Monoid, Functor, and Applicative!

Implement the standard library monads ( List, Maybe, Cont, Error, Reader, Writer, State ) for yourself to understand them better. Then maybe write an monadic interpreter for a small expression language using Monad Transformers Step by Step paper.

Writing many interpreters by just changing the monad to change the semantics can help convey what's going on.

Also, reimplement Control.Monad. Functions like mapM or sequence are good opportunities to practice writing generic monadic code.

The NICTA course can be used as a guide to this process, which will also involve writing your own Applicative as well.

From:

Monad transformers

Testing, tests, specs, generative/property testing

Resource handling, finalization, cleanup

Streaming IO

Recursion Schemes

Some of the crazy *-morphism words you've heard are actually about recursion. NB - before tackling this material you should know how to implement foldr for lists and at least one other data structure, such as a tree. (folds are catamorphisms) Knowing how to implement an unfold (anamorphism) for the same will round things out a bit.

This material dovetails with traversable and foldable.

Type and Category Theory (not needed to actually write Haskell, just for those interested!)

If you want to follow up on the type and category theory:

Stephen's Nifty "How to get to monad" posts

Didn't know where else to put these:

Parametricity, ad-hoc vs. parametric polymorphism, free theorems

Initial and Final, DSLs, Finally Tagless

Comonads

Yoneda / CoYoneda

IO

Comment from Reddit thread by glaebhoerl

Interesting side note: GHC needs to hide the state token representation behind an abstract IO type because the state token must always be used linearly (not duplicated or dropped), but the type system can't enforce this. Clean, another lazy Haskell-like language, has uniqueness types (which are like linear types and possibly different in ways I'm not aware of), and they expose the World-passing directly and provide a (non-abstract) IO monad only for convenience.

GHC Core and performance tuning

Dependent typing

Propositions vs. Judgments (computation)

Graph algorithms and data structures

Extended Reading list (some is already included here)

Stackage

For any users (usually Yesod users) that have build problems, consider Stackage.

In the author's opinion, Stackage is usually more useful than cabal freeze.

Dialogues

Dialogues these are actually pretty important and helpful. Look here for deep dives on a variety of topics.