Monday, March 16, 2020

The <- pure pattern

Summary: Sometimes <- pure makes a lot of sense, avoiding some common bugs.

In Haskell, in a monadic do block, you can use either <- to bind monadic values, or let to bind pure values. You can also use pure or return to wrap a value with the monad, meaning the following are mostly equivalent:

let x = myExpression
x <- pure myExpression

The one place they aren't fully equivalent is when myExpression contains x within it, for example:

let x = x + 1
x <- pure (x + 1)

With the let formulation you get an infinite loop which never terminates, whereas with the <- pure pattern you take the previously defined x and add 1 to it. To solve the infinite loop, the usual solution with let is to rename the variable on the left, e.g.:

let x2 = x + 1

And now make sure you use x2 everywhere from now on. However, x remains in scope, with a more convenient name, and the same type, but probably shouldn't be used. Given a sequence of such bindings, you often end up with:

let x2 = x + 1
let x3 = x2 + 1
let x4 = x3 + 1

Given a large number of unchecked indicies that must be strictly incrementing, bugs usually creep in, especially when refactoring. The unused variable warning will sometime catch mistakes, but not if a variable is legitimately used twice, but one of those instances is incorrect.

Given the potential errors, when a variable x is morally "changing" in a way that the old x is not longer useful, I find it much simpler to write:

x <- pure myExpression

The compiler now statically ensures we haven't fallen into the traps of an infinite loop (which is obvious and frustrating to track down) or using the wrong data (which is much harder to track down, and often very subtly wrong).

What I really want: What I actually think Haskell should have done is made let non-recursive, and had a special letrec keyword for recursive bindings (leaving where be recursive by default). This distinction is present in GHC Core, and would mean let was much safer.

What HLint does: HLint is very aware of the <- pure pattern, but also aware that a lot of beginners should be guided towards let. If any variable is defined more than once on the LHS of an <- then it leaves the do alone, otherwise it will suggest let for those where it fits.

Warnings: In the presence of mdo or do rec both formulations might end up being the same. If the left is a refutable pattern you change between error and fail, which might be quite different. Let bindings might be generalised. This pattern gives a warning about shadowed variables with -Wall.

Monday, March 02, 2020

How to get a Haskell job

Summary: There are four things I recommend to get a Haskell job. Applies to most technologies.

I was recently emailed by someone who asked for advice on what they could do to get a Haskell job in the future. Rather than share my reply only with them, I thought I'd cc the world via my blog. I'd give the same advice if asked about how to get a job focusing on any technology, just changing the examples. While the pieces of advice explain how they can be used to get a job, I believe they are all useful in their own right too!

Write Haskell

The most important thing to get a job in Haskell, is being fluent in Haskell, which can only be done by writing real Haskell programs/libraries. Solving small exercises or challenges will help a bit, but there are some limitations/solutions/approaches that you only learn when trying to do something for real. For beginners at Haskell, I recommend taking whatever you are interested in outside of Haskell, and writing a library about that. It can be image codecs, statistics, lasers, poker - whatever. There's probably something you know a lot about, which most people don't, which gives you a good starting point. That library will convince future employers you know how to write good code, and in the best case, you'll find an employer ends up using your library. Hiring people whose work you already use is an easy decision. When I've hired programmers in the past, I treat their CV as a pointer to their GitHub account.

Meet Haskellers

In most cities there are a bunch of either Haskell of functional programming meetups. Usually Meetup will have them, but a Google search can find them too. If there's nothing near you, try a more global event like ZuriHac or Haskell Implementors Workshop. These events give you an idea how other Haskell programmers think, and there are always people who are currently employed to write Haskell, who might offer you a job. Some of these Haskellers will even become friends who you collaborate with over decades.

Write words

As you are learning, write down what you are learning, what you are thinking, the hurdles you overcome and the thoughts you have. In many cases, no one will listen, but the mere act of writing down the words serves as a record of what you are learning. In some cases, you'll find an audience, and that audience will give you credibility (which isn't real credibility, but the world is a funny place) and contacts which can be useful in getting you a job. When I started, I wrote on my blog, but now Twitter or Medium might be better. Maybe it should be Twitch streams or SnapChat messages - I've no idea. Do whatever works for you. When I got my first Haskell job, I had colleagues who didn't know who I was, but had already been reading my blog.

Read news

It's important to have a rough idea of what's happening in the Haskell world. For Haskell, you might read Planet Haskell, some mailing lists, follow some people on Twitter, or read academic papers like those at ICFP. Nowadays there is so much information it's impossible to keep on top of it all, and if you try, you'll end up neglecting the other pieces of advice. Reading news won't directly get you a job, but it will expose you to a variety of techniques that keep you learning more.