elm-syntax icon indicating copy to clipboard operation
elm-syntax copied to clipboard

Use nonempty list to make impossible syntax impossible

Open MartinSStewart opened this issue 4 years ago • 7 comments

There are a few places in elm-syntax where using List.Nonempty* instead of List could prevent needing to deal with impossible cases.

The ones I've been able to find are

  • Elm.Syntax.Expression.RecordUpdateExpression - Having no record setters would correspond to { a | } which is invalid syntax.
  • Elm.Syntax.Expression.Application - Not sure how to give an example of this one. If the list is empty then there's just nothing there right?
  • Elm.Syntax.ModuleName.ModuleName - Here I can understand why it's like this. Elm.Syntax.Expression.FunctionOrValue can have an empty ModuleName because functions can be local or exposed. However, in import statements, having a ModuleName that's just an empty list would look like this import exposing (..) which is invalid syntax. One solution is to have to two versions of ModuleName, one is a list, one is a nonempty list. Another solution is for FunctionOrValue to treat the last element in the nonempty list as the function/value name.
  • Elm.Syntax.Exposing.Explicit - Empty list results in exposing () which is a syntax error.

*By List.Nonempty I mean this package but an alternative could be to just have (a, List a).

MartinSStewart avatar May 07 '20 17:05 MartinSStewart

~I realized that using List.Nonempty isn't a good idea since it would prevent pattern matching on the result. (a, List a) is probably the way to go.~

Edit: Nevermind, I noticed it's possible to deconstruct List.Nonempty too.

MartinSStewart avatar May 08 '20 07:05 MartinSStewart

You could also consider using https://package.elm-lang.org/packages/turboMaCk/non-empty-list-alias/latest/ which uses (a, List a) to represent nonempty list and just adds functions for working with that type.

jhrcek avatar May 09 '20 04:05 jhrcek

@MartinSStewart this can be closed now, right?

jfmengels avatar Jun 15 '20 11:06 jfmengels

I only made a pull request for this bullet point Elm.Syntax.Expression.Application. The rest hasn't been addressed.

MartinSStewart avatar Jun 15 '20 11:06 MartinSStewart

Ah yes, my bad :+1:

jfmengels avatar Jun 15 '20 11:06 jfmengels

For FunctionOrValue, the module name could also be Maybe ModuleName, which i think would remove the need for a separate potentially empty module name.

jfmengels avatar Jun 15 '20 11:06 jfmengels

I spoke with @stil4m on Slack about what type signature to use for nonempty lists. We settled on Application (Node Expression) (List (Node Expression)) rather than use Application (Node Expression, List (Node Expression)) or List.Nonempty.

The reasoning for this is that it reduces how much syntax is needed when doing pattern matching. This comes at the expense of making it a little harder to use https://package.elm-lang.org/packages/turboMaCk/non-empty-list-alias/latest/ but we decided this tradeoff is worthwhile as the user will likely be doing a lot of pattern matching and deconstructing expressions.

MartinSStewart avatar Jun 15 '20 12:06 MartinSStewart