Haskell

New practioners of Haskell may find themselves guided by this page. Here
are things I wish I knew when I started learning the language. This page
may be slightly out of date; I need to update it.

XMonad

XMonad is a wonderful tiling window manager that also happens to
be written in Haskell. You can grab it with cabal install xmonad. Plenty
of people have published their xmonad.hs files, so I won't belabor the point,
but here are some useful tricks I've accumulated:

If you use .xsession to start up XMonad from GDM without using
gnome-session, you should also
start up gnome-settings-daemon, gnome-power-manager
and gnome-screensaver. Among the things these will fix include
your power button, locking your screen and your desktop background.

I hate gnome-panel with a passion, but without some sort of panel
you can't run Network Manager. I use stalonetray,
with the flags -bg '#000000' -i 8 -geometry 19x1+680+0: in particular,
-i 8 sets the icon size to something that fits snugly in a default xmobar. Once
the tray is running, spin up nm-applet.

Literature

I learned with Real World Haskell
and Brent Yorgey's Typeclassopedia.
Real World Haskell will give you a practical introduction to Haskell's
syntax and functional programming, and give you some cunningly written
examples of monadic code. Typeclassopedia will give you the
theoretical foundation to understand the progression from functor to
pointed to applicative to monad. Learn how to implement all of the
common monads from scratch. Be competent with both >>=
and the do sugaring. return does not
short-circuit execution.

Hoogle

I Hoogle. Do you
Hoogle? I have Hoogle setup as a keyword shortcut in
Firefox, under the letter h. I also have it
locally with cabal install hoogle. Use it
to find what module functions are in, lookup those weird
operators like >>> and <*>,
and discover new functions from type signatures.

Types

So you got a type error. How do you go about fixing it?

Do you have an explicit type signature for the top-level?
Is it correct? What does Haskell infer if you leave it out?

Replace parts of your expression with undefined
until it typechecks, then figure out where the mismatch was.

Rewrite the function from scratch. It's short, right?

If you're running into type errors with monadic code, pay
close attention to where the m is in the inputs
and outputs of your functions.

liftM

(a -> b) -> m a -> m b

ap

m (a -> b) -> m a -> m b

=<<

(a -> m b) -> m a -> m b

$

(m a -> m b) -> m a -> m b

return

a -> m a

Did you ask #haskell?

Exercises

I find working through mind-bending problems is a good way
to test how well you've figured out a concept and also get
intimately familiar with details. Here are some problems
that should
be done as you work your way through Typeclassopedia.

Functors

Implement fmap for Either e,
((,) e) and ((->) e).

Write a function with type signature
Functor f => (a -> b) -> f (f a) -> f (f b).
If you are stuck, try writing the function for a specific instance
of functor. Can this type signature be generalized?

What is the type of fmap fmap? Specify
both using Functor f => and explicitly.
Remember that all functions in Haskell are automatically curried.

What is the type of fmap fmap fmap?

Pointed

Implement pure for [] and
((->) e).

Assuming a well-behaved functor that follows the laws
fmap id = id and fmap (g . h) = fmap g . fmap h,
prove that fmap g . pure = pure . g for all definitions
of pure. (Nota bene: a rigorous treatment of
this question may require Wadler's theorems for free, which is not
for the lighthearted.)

Applicative

What symbols are used for the infix version of fmap?

Implement <*> for Maybe,
[] and ZipList.

Implement <*> for ((->) e).
This is tricky.

What is the value of [(+1), (+2)] <*> [4, 5]?

What is the type of const <*> id? Rewrite this
expression in a form that makes this obvious from the applicative
law fmap g x = pure g <*> x.

Errors

Errors can be broadly be divided into
two types: pure and impure. Pure errors utilize data types
like Maybe, Either or
MonadError and are used monadically to short-circuit
execution. Impure errors mean that the function
returns "bottom" (a "value" that means the computation cannot
terminate) and possibly have additional semantics attached
to it, such as error (prints string error message)
or asynchronous exceptions.

Pure errors are what you should turn to first when you find
yourself in need of some sort of error reporting mechanism.
Descriptive pure errors also fall into several categories: some
errors are intended to be "caught" and then result in execution
flow change, while others are unrecoverable and intended to
be passed straight to the user.