A spoonful of Enum

We’re writing the Python course in a slightly different style from most of Type Classes, because it is aimed at a more focused audience. The idea is that if you are already familiar with Python, then we want to leverage as much of your existing Python knowledge as possible as you learn Haskell. For example, we’re not including quite as many type signatures in our explanations as we normally would, and we defer the introduction of some aspects of Haskell to minimize the amount of patience required if you just want to answers to questions of the form ‘I know how to do this thing in Python; how do I do it in Haskell?’ This post is about one particular small choice regarding range syntax.

Haskell range syntax is nice, but so far we’ve avoided using it in the Python course. The Python expression itertools.count(5) translates to the Haskell enumFrom 5. We could also write [5..],And indeed in most actual programs, we would choose to write this as [5..]. but it’s much nicer to explain “enumFrom is the same as the count function, just with a different name” rather than “well there’s this special syntax…”

What we love about Haskell is that the mental model of evaluation sits on a few foundational ideas. Expressions in the language represent values, and a function can be applied to a value which reduces to yield a result. It clearly wouldn’t be fair to say And that’s all there is to it, now go do functional programming! because these ideas by themselves don’t tell you how to design software, but this model of computation provides a constant source of comfort and stability throughout the journey. Those foundational ideas never become irrelevant or get superseded by subsequent revelations of Well actually, the truth is more complicated than what we told you at first…

Sugar isn’t bad – at least, not always. The risk with special syntactic features is that they may separate us too far from the foundation and begin to deprive us of that helpful mental model. Syntactic sugar is mostly harmless if the translation into normal desugared expressions is straightforward and well-known, and is widely understood as a notational convenience rather than as a critical feature.

We find these notational translations in Haskell to be mostly harmless:

  • [x ..] represents enumFrom x, See the definitions of these functions in the Enum class. e.g. [5 ..] produces a list of 5, 6, 7, 8, (continuing on indefinitely).
  • [x .. y] represents enumFromTo x y, e.g. [5 .. 10] produces a list of 5, 6, 7, 8, 9, and 10.

This one, perhaps, begins to cross the line:

  • [x, y .. z] represents enumFromThenTo x y z, e.g. [2, 4, .. 10] produces the even numbers 2, 4, 6, 8, and 10.

We seriously doubt that many people have the function enumFromThenTo in mind when they read an expression like this. It feels much more to us like It looks sort of like whiteboard notation and I suspect I can guess what will happen, and this is not how we prefer to do programming.

Moreover, we find these sorts of one-off syntax rules to be anxiety-inducing, because:

  • Many programmers have been burned before by desugarings that promise to have a straightforward translation but actually contain hidden gremlins, and so it can be difficult to trust them.

  • In the very early phases of learning a programming language, when we’re still struggling with mentally parsing the grammar, each encounter with a new spoonful of sugar prompts us to wonder:

    • Where does it end? How many syntax rules will I have to learn to use this language?

    • Do these special forms exist because the language wouldn’t be good enough without them? Should I infer that if I’m working in a domain that the language designers were unfamiliar with and didn’t design special syntax for, the language will be unable to accommodate my needs?

We don’t dislike range syntax, and we don’t think it needs to be avoided even in beginner material. But we’re avoiding it when writing for wary audiences, which is a group we intend our transitions material to satisfy.

When you come at a new language, some amount of skepticism is warranted. The code we choose to present needs to meet that skepticism with plain examples of the ideas that we claimed are foundational: expressions, values, functions, and application.

All of our Python and other transitions material is available for free. If you decide to continue pursuing Haskell in further depth, consider becoming a member. The annual price is $300, and it is currently half-price during our anniversary sale through the end of June.