The following post is part of Spoke Proof. Tell your friends.
Many people coming into Haskell are daunted by number of choices they have to make: which package to use, which package manager to use, which language extensions to turn on, which resources to read.
So here are some sensible default choices. I’ve noted wherever the answer is still up in the air. Most things are! Many problems in our world have good, but not great, solutions.
Setting up a Haskell environment on OS X
Use stack. Stack
Is a sandbox-style package manager. For each project it creates a hermetic little world filled with the project’s dependencies and the project itself.
Sets up a “global” project, which is the default project you work in when you run stack outside a project.
By the way, a project is any directory with a
package.yamlfile or any subdirectory thereof. I highly recommend using
package.yamlfiles, otherwise known as the hpack format. With
*.cabalfiles you have to type the name of each module separately and you have to maintain per-target dependencies. What a hassle.
Also installs GHC (
stack setup) for you.
Also maintains your
PATH. If you run
stack exec fooor
stack ghci, you’re running
ghciin the context of your project’s sandbox.
Awooga: OS X users will be tempted to use Homebrew to install Stack but that will compile it from source, which takes a good hour on a desktop and possibly longer on laptops. (I have never been patient enough to find out.) Best to just unzip an official release.
Is the best part of Haskell. The community is incredibly kind and supportive. /r/haskell is a medium-traffic subreddit filled with library announcements, fascinating discussions, questions answered by experts, and much else besides. Try Stack Overflow too.
What I Wish I Knew When Learning Haskell by Stephen Diehl
Write You a Haskell by Stephen Diehl
The original paper by Philip Wadler that proposed the Monad typeclass – surprisingly readable
Cryptopals – not the worst way to learn Haskell, and you’ll learn modern applied information security to boot (You will probably need Crypto.Cipher.AES128 or Crypto.Cipher.AES.Haskell to complete the first chapter.)
Chris Allen’s “How to learn Haskell”, another collection of links. Has perhaps the best advice written about Haskell: Don’t sweat the stuff you don’t understand immediately. Keep moving!
Creating a new package
$ cd ~/workspace $ stack new hello
$ stack templates
The pain of compilation
Compiling Haskell is slow. Add this to your global aliases (assuming you use zsh):
alias .fast='--fast --ghc-options="-j +RTS -A1024m -n2m -RTS"'
It will teach GHC to use (1) all your cores and (2) more memory while compiling.
Another useful global alias (assuming you use zsh):
stack build .fast .fw
stack ghci .fast
stack install lens .fast
Another suggestion: rebind
: in your terminal preferences. When Haskelling I never type semicolon but I sure do type colon all the time.
You can’t go wrong with my Haskell Emacs scratchpad. Emacs and Vim are both pretty good choices. Really you need these things:
Live parsing and typechecking
Autocompletion of horribly long module names
Being able to send code to an interactive GHC REPL
Restarting the REPL when your
Being able to go from
f x = x
f :: a -> a f x = x
with one keypress.
With the right packages, Emacs and Vim have all these features.
IDEs: hdevtools or Intero
This is an active field of development!
hdevtools runs a GHCi process in the background and lets your editor interactively query it for typechecking and code-reloading purposes. Comes with integrations for Emacs, Vim, Atom, and Sublime. This is the one that I use.
Intero is an Emacs-specific IDE and a rising star. I have not used this much but people speak highly of it.
Use warp. It implements WAI. If you’re coming from Python, WAI is Haskell’s WSGI. Or Ruby’s Rack. Or Perl’s PSGI.
This is an active field of development!
This is more divisive. I like to think of each web framework by what new technologies and abstractions they use. These three have all picked very interesting choices, making the Haskell web framework field very diverse:
Snap: Snap uses lenses in a neat way that lets you attach additional information to the request at each middleware layer. I think I’m drastically oversimplying snaplets.
Yesod: Yesod has great documentation. It also uses conduits, which is a neat little library for modeling streams (with – and this is the hard part – reasonable memory management and error handling) in Haskell. It uses Template Haskell to remove some of the boilerplate of web programming.
Servant: Servant is newer but has a cool higher-kinded routes system where you can declare the type of your entire API with type-level programming.
This isn’t like Python or Ruby’s web framework ecosystem, where everybody has sort of decided to coalesce around a monolithic, invent-the-wheels framework (Django, Rails) with lots of smaller, more modular options (Camping, Sinatra, Flask). Lens, conduits, and type-level programming are all cutting-edge stuff.
Use Data.ByteString. If you need to represent text, upgrade yourself immediately to text.
Lazy text or bytestrings?
I would say avoid them unless you really know what you’re doing. I say this as somebody who doesn’t know what he’s doing.
Lazy IO causes more heartache with resource management and error handling than you would expect. Try pipes or conduit instead, which lets you build out streaming data pipelines without leaking file handles or badly handling IO errors. Unfortunately they’re both a little hard to use.
This is an active field of development!
The most comprehensive and well-organized OpenGL library for Haskell is gl by Edward Kmett. How it works is elegant: it downloads the OpenGL specification into a
gl.xml file and then it produces a Haskell library from that XML file. Code that writes code. Its documentation is poor, however; for a tutorial see the primer on Wright Access. For toy examples, see ekmett/quine. Unfortunately the graphics story for Haskell is not quite all there yet.
You’re going to keep hearing about lenses because the lens package has achieved remarkable success in the past couple of years, both in terms of creativity and popularity. This series of blog posts takes the time to explain and derive lenses. Lenses tutorials have the same problem as monad tutorials. The reason lenses and monads exist is long-time Haskellers all noticed the same problem, and a lot of (abstract) thought went into thinking of a solution. The original sin of lenses is functionally updating a complicated data structure. The solution is … complicated.
Some lens tips and tricks:
Prisms, getters, setters, traversals, and uppercase-L
Lensin the lens package all compose with
.It all typechecks and type-inferences. This seems simple but it isn’t. It is one of those inventions, like Isaac Newton’s catflap, that does the magic of rendering the blindingly simple into existence. And that’s the secret genius of the lens package: against all odds, they got all the optics to compose with with
.. (Aside: It is impossible in most other languages as it takes advantage of two unique Haskell features, rank-_n_ polymorphism and typeclasses.)
If you compose a bunch of lens together, you get back the lowest common denominator on this UML diagram. So composing a setter with anything automatically makes it the result a setter. And you can’t compose a setter with a getter – you need a
Lens. And a
Lenscomposed with a traversal is always a traversal. And only compositions of isomorphisms will yield an isomoprhism. Against all odds, they got all this UML diagram to work exactly as you think it would.
99% of lens usage boils down to
bigDataStructure operator (lens1 . lens2 . lens3), where operator is one of
toChunks/fromChunksto convert between strict and lazy bytestrings (and texts). Use Control.Lens.Iso instead.
The default prelude is super annoying because you keep importing tiny minimodules like
Data.Maybe to get their helpers. The base-prelude package does all this for you, but you have to turn off implicit preludes (
blunt is a little web app that gives you the pointfree version of any function. Be prepared to encounter headache-inducing oddities like
(.) . (.) or the
Applicative instance for
Searching by types
A good thing to watch out for is functions in Haskell that last for longer than five lines. These might take the form of long
do blocks, or a mess of
let ... in ... s and
wheres. These often signal that the function is doing too much. Whereas in other languages we might resign ourselves to the mess, in Haskell we can do better.
I find writing a clean function
f involves asking myself:
fis the composition of some series of functions?
f = foo . bar . bazis one kind of function composition. But so is
f = foo >>= bar >>= baz(and its categorical cousin
f = foo >=> bar >=> baz).
fa map over some structure? If I’m taking a list and producing a list, I usually reach for
ffolding a big structure into a smaller structure, which aggregates or summarizes the information in the big structure? If I’m taking a list and producing a single value, I usually reach for
Upcoming GHC developments we should be excited about:
Great Haskell blogs
Haskell for all by Gabriel Gonzalez
Neighborhood of Infinity by Dan Piponi
Inside 736-131 by Edward Z. Yang
Simon Peyton Jones – don’t be put off by the academic paper format, as spj is a highly capable technical writer
Parametricity a.k.a. theorems for free
Using types and typeclasses to generate and prove theorems about a function’s invariants. This is like if all your life you carried around this intuition about how something works and then one day someone came along and validated all of it with mathematics and good writing.
Parametricity: Money for Nothing by Bartosz Milewski
Parametricity Tutorial (Part 1) by Edsko de Vries
Theorems for free! by Philip Wadler
Opting into strictness
seq and weak-head normal form? Read Roman Cheplyaka’s blog post on forcing lists.
The older you get, the more you’ll appreciate a moderate amount of fiber in your daily diet.
Try Ubuntu Mono!
Updates to this document
2015 Nov 30: the initial draft was published after a rousing discussion in my friends and I’s #haskell Slack channel.
2016 Jan 3: added Web Sockets mention after a fun day with Slack’s real-time messaging API.
2016 Aug 18: hdevtools and intero mentioned. Typos fixed.