Hi Max,
Thanks for your detailed reply! First, I want to thank you for your wonderfully clear and beautifully written reply.
I'm afraid, though, that I was trying to aim at what I think is a deeper question, that is: now that Elm's syntax doesn't expose the record modification operators that were (or implied) a sort of type-level function, does it still make sense for the usual shorthand for a record type to be a type alias? And if not, should it even be possible to talk about records that aren't part of a union type?
I'll try to unpack that first question a little - there's a bit of a jump in the middle of it.
The reason I ask is that when elm had record extension, implying a sort of type level function, there was a definite synergy between that feature and choosing to use aliases to refer to record types. This is because the type level function of extending a record works like a sort of algebra that provides addition (when you add a record) and equality (when your code causes the type checker to try to unify two record types), and type equality looks through type aliases in such a way that if you give names to all of the types involved in that sort of manipulation, things Just Work. I'll provide an example, with code that won't work but will hopefully explain the idea:
type alias Person = { name: String }
type alias Parent = { name: String, children: [Person] }
harry_potter = { name = "Harry Potter" }
james_potter_at_hogwarts = { name = "James Potter" } -- this has type Person
james_potter_on_harrys_first_birthday = { name = "James Potter", children: [ harry_potter ] } -- this has type Parent
have_first_child person child = { person | children = [child] } -- this is a Person -> Person -> Parent, because a `Person + { children: [Person] } = Parent` (that's a completely-imaginary type-level expression)
james_potter_on_harrys_first_birthday == have_first_child james_potter_at_hogwarts harry_potter -- this is true, despite the two having been constructed in different ways.
So far, so simple. But what's going on at the type level in have_first_child? The expression that is that function's body takes a record that has some set of fields, and adds a field `children`. So a type goes in, and the type that comes out is that type's fields plus the field `children`. This fits in nicely with type aliases because when you add `children` to the Person type, you get `Parent`. If `Person` and `Parent` were parts of tagged unions, that wouldn't work: you'd have to un-tag to remove the `Person` tag and re-tag the `Parent` tag.
My guess, looking at elm tutorials and source code and stuff, is that this tidiness, this synergy between aliasing and extending records, is the main reason why records are typically addressed by a type alias in the elm world at present. But with the removal of that feature, one of the legs of the tidiness gets knocked out from underneath it. Which I think means the benefit of defaulting to type aliases to refer to records goes away.
This wouldn't mean it made sense to change anything, except that people do seem to be being confused by the distinction in existing code between type for unions and (defaulting to) type alias for records, which is the confusion that sometimes makes emails like your fabulous reply necessary.
So if the thing that made it good doesn't make it good any more, and there's something that's making it bad, maybe it's time for a change. Maybe it makes sense to not default to type aliases as a way of referring to record types. And maybe it makes sense to not even allow records to be defined outside a tagged union?
I want to point out here that I am supposing a bunch of things, and I don't know how true they are:
1. In most elm code, when defining a name to provide a shorthand way of referring to a record type, the default is to type alias.
2. The main reason for this default was a synergy with record extension.
3. Enough people are confused by the type/type alias thing that it's worth talking/thinking about changing (the confusion of the transition may well not be worth it)
There are bound to be other things too, as I am pretty much a lean mean supposition machine.
Anyway! In my newness to the elm world, I felt like I might have spotted an interesting gap between the way elm code is written and what makes most sense for elm-the-language as an easily-learned and generally joyful thing. Hence this email, which I hope (probably in vain) is not quite toooooooooooo long.
-Iain
--
You received this message because you are subscribed to a topic in the Google Groups "Elm Discuss" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elm-discuss/0XbEEb4hkjM/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elm-discuss...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
your wonderfully clear and beautifully written reply.
Maybe it makes sense to not default to type aliases as a way of referring to record types. And maybe it makes sense to not even allow records to be defined outside a tagged union?