the mind can learn

the zen of

monads ∙ morphisms ∙ multicore

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.

to start up XMonad from GDM without using , you should also start up , and . 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 .

with a passion, but without some sort of panel you can't run Network Manager. I use stalonetray, with the flags : in particular, sets the icon size to something that fits snugly in a default xmobar. Once the tray is running, spin up . Transparency is good. Windows that spawn on the same workspace that you requested are good.

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.

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) .

for , and . 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?

. 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.

? Specify both using 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) .

for and . 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 .

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

for . 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 .

? Rewrite this expression in a form that makes this obvious from the applicative law . What is the value of ((+) <*> (+3)) 5?

Write fmap with pure and <*> .

with and . Write liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c with only <$> and <*> .

Errors