Gren format does not remove unnecessary parens

The new gren-format tool does not remove unnecessary parentheses. First of all, this is very nicely documented within a list of settled decisions. This decision might seem surprising, but I think it’s right. Why would you put unnecessary parentheses in, unless you thought they increased clarity? In my first year of a computer science degree (last century), I recall an exam which included questions about operator precedence in C programs. I recall thinking this was a dumb exam question that tested recall and nothing important. As young and foolish as I was then I think I got that assessment right. I’m still unsure if I could accurately state the operator precedence rules in most of the languages I use. Firstly, I typically do not write complicated mathematical expressions without giving names to intermediate results. Secondly, if I’m at all unsure I just put the parentheses in and, there is no problem. I often put the parentheses in even if I am sure. I know that * binds more tightly than +, but still I don’t see the problem in writing: ...

August 28, 2026 · Allan Clark

Link: Gren format challenges

Gilbert Ramirez has written a good post-mortem on the challenges of writing Gren format. I’m a huge fan of formatters, and the kind of opinionated formatter that is gren-format (and elm-format) are especially good. I promise, even if you have strong opinions about formatting and think that you won’t get on well with a non-configurable formatter it is well worth getting over that initial grinding of gears. The amount of cognitive load that is reduced by not having to being able to think about formatting decisions is larger than certainly I predicted. ...

August 28, 2026 · Allan Clark

Laziness would be good for Time.Extra.posixToParts

In this post I’m going to show a good example of where laziness would work well. This is of course not an argument that lazy programming languages are somehow better than strictly evaluated programming languages. Rather what I wish to do here is answer the question, what is laziness good for? My example here comes from the justinmimbs/time-extra Elm package. The main purpose of this library is to provide a means for working with the standard library’s Time.Posix values. Functions are provided to calculate the difference between two time values, and also to add/minus a given interval from a given time value. So for example it provides a convenient way to take a given time value and add one day, or two hours, or six months. ...

October 27, 2022 · Allan Clark

No more imports

Imports in most languages always seem like a bit of an add-on, a separate language to the actual language. Today’s post is a thought experiment regarding removing imports from Elm/Gren. Ultimately I think it’s probably worthwhile having the import statements there, but this is an interesting (and quick) thought experiment. If we remove import statements from the head of a module file the first thing to note is that a file then becaomes one module declaration line followed by simply a list of top level declarations. However, we would obviously need someway to refer to values and types defined in another module. ...

October 6, 2022 · Allan Clark

Structural Custom Types

There have been a few proposals for extensible custom types in Elm, the idea is that they are somewhat analogous to extensible record types. In this post I wish to give a proposal for how to make custom types ’extensible’ that could play well with opaque types. The key point is that we need not focus on extensibility so much as the distinction between structural and nominal types. The slightly longer summary is to say that we can make custom union types structural types. This means that custom union type declarations are actually type aliases, just as record type definitions are in Elm. Two record types can share the same field, and thus it is trivial to make two record types one of which is a sub-type of the other. Similarly if custom union types are structural, and their associated definitions type aliases, two such custom union types can share a constructor, and again it is trivial to create two custom union type definitions one of which is a sub-type of the other. With this apparatus we can implement opaque types by choosing to expose a type either nominally or structurally, this gives us opaque types in which the underlying type can be a primitive type, a function type, a record type or a custom union type. ...

June 29, 2022 · Allan Clark