Just over all proposed alternatives.
Some is also well-known, but not worth the breaking change.
I think a user study would be interesting, but
NoValue is so clear and intuitive that I’d support that change without a study.
Nothing would be fine with me as well, and that would be the most minimal change.
Nothing is interesting as a linguistic parallel to
NoValue, but I like the first two better.
Maybe is definitely clearer than
I just started looking into Elm and think that Just for Maybe is a very reasonable choice.
I learned Maybe type in two stages. Initially, when I read type like “Maybe String”, I knew that “it may be a String or Nothing”. You can see that I’ve ignored Just, but Maybe and Nothing stand out as really good names. Also, Maybe is a much better name than Option or Optional.
Then I tried to fit Just into the above. At first I considered “it may be just a String or Nothing”, but it felt redundant as it didn’t add anything new to the above. Then I considered “it may be a Just String or Nothing” and this made a lot more sense, because in this context “a Just String” actually means “a valid string”. I think that Just is a pretty good name and definitely better than Some.
What I like about
Maybe is that the name is very unique and it’s pretty much guaranteed to mean only one thing in a codebase. If we consider the
Option alternative, it may be some custom type for a dropdown or a setting, also when naming a variable
maybeUser is ubiquitous, while
userOption can mean a lot of things that are not actually an optional value.
Nothing is also less frequently used in userland than
NoValue, which again could be constructors for some custom types.
Lastly, this argument applies even more for
Value, which while some may consider a little bit less misleading, I think the uniqueness of
Just make it instantly recognizable and understandable in any codebase no matter what the domain is.
Just has always felt strange to me but I would not want to see it replaced at this point. Elm has already accrued lots of changes that make old code invalid. All those blog posts, SO answers, etc. aren’t going to be updated and the discrepancies are off-putting to newcomers. The more there are, the worse it gets.
Every language has its quirks (flavor, if you prefer). Let this be one.
Wow, this topic proved to be far more provocative than I’d expected.
The only reasonable resolution at this point is to say that we’ve all been considering the wrong definition of “Just”. We’ve been focusing on the adverb while we should have been thinking about the adjective:
“conforming to a standard of correctness”
One more idea for the cute bikeshedding/brainstorming thread:
If we wanted to appeal to the OOP crowd…
type Object a = Is a | HasNothing
A few related thoughts:
The variety of definitions and interpretations of the various options here suggests to me that the
Just foo value is one of those things where any good enough name is worth sticking with.
The difficult concept for the beginner coming from a world with unchecked
nulls I think comes less from the name of
Just foo but the fact that you can’t treat a
Just foo : Maybe a like an
a directly; you have to do case analysis on it. (I sort of remember this being confusing to me when learning about
Maybe through Haskell ages ago.)
One arguable advantage of
Just being an odd choice of word for naming one of the value constructors of
Maybe is that it’s unlikely to be a name the programmer wants to use for something else.
I’ll throw my hat in the ring too:
Maybe a = Nothing | Actual a
foo is a
Maybe String, then it is either
Nothing or an
I think ‘Just’ as a term complicates everything as much as ‘Union type’ did - without any reason. It would be strange for me, considering Evan’s thoughts about redundancy of the academic functional terms in the process of grasping underlying ideas of the functional programming, if it survives in the future. I struggled with it and wasn’t as productive as I could be if the naming was more obvious. Just my experience though.
I thought back to my first encounters with
Maybe and I think the hardest part was understanding why I had to write something at all. In Java (or C#, or Python, or …) I can have
null without having to write
just in front of every other value, after all!
Of course, there are good reasons why a tag is necessary. But maybe the difficulty is explaining this necessity to beginners instead of the precise name this tag takes.
Here is my suggestion:
Maybe a = Nothing | Is a
with context that becomes
doStuff maybeString = case maybeString of Is "Hello" -> Nothing ->
Very easy to understand in case of expressions.
That’s pretty cool! Reads well as English.
It kind of makes sense without the argument too - it just “is”
like “To be, or not to be…”
I like @dta’s suggestion of
Maybe a = Nothing | Actual a! I was leaning toward
Value a | NoValue, but “value” can also imply a quantitative number. Think of “market value” and “the screen will display a value”.
But more seriously, I’d actually say that it shouldn’t be changed at all. Elm clearly comes from Haskell (as opposed to ML) roots and it’s great in the broader context of the field to reuse some of the same arbitrary terminology. Then people don’t have to learn different names for the same concepts when they go to different languages. Functional keywords are fractured enough without adding to the mess. I wouldn’t want any change even though I come from a largely ML background myself, and would of course find
None to be more natural…
I’d argue further that given that it’s been the word for so long in Elm, that even if it was a divergence from Haskell, it shouldn’t be changed.
TLDR: our concepts need a name, and it really doesn’t matter what name we give them, as long as it’s distinctive and memorable.
Words have meaning because we give it to them, and as we use them more and more in a given context, the meaning we give them in that context becomes second nature to use. Having a name that borrows meaning from another context (what we call “meaningful names,” implying that they already have existing meaning before we re-appropriate them) can be helpful for beginners, but can be a difficult transition for those already accustomed. In this case, it probably wouldn’t be the end of the world, but it would cause a lot of us to have to expend extra effort.
I would value distinctiveness far over meaningfulness. When I have a partial understanding of a concept, having a closely related, similar sounding concept in the same context can be really challenging to my learning. “Monoid” and “Monad” in category theory. The underlying greek root doesn’t really have much meaning to me, and the words are so similar that I often confused them. (But now that I understand them, I do mentally reach for the word Monad and Monoid when I conceive of the underlying concept, and it would take some mental effort to replace this vocabulary).
And I don’t think we should easily discount the mental difficulty in changing vocabulary once it’s in use. I still confuse “Kernel” and “Native”, and it slows me down and makes reasoning harder. Not a lot harder, just a little, but still…
Not to say that we should never, ever, ever improve our naming choices…I think Haskell would be well served by ditching some of the very mathematical typeclass names, but it is a trade-off, and I generally think we should air on the side of caution, once a thing is named.
type PossiblyNil a = NotNil a | Nil type NPlusOne a = N a | One type Vielleicht a = Nur a | Nichts type CouldBe a = Is a | Isnt type DudeWheresYourCar a = RightHere a | WheresYourCarDude type TheGreatComputer a = HasSaid a | IsStillThinking
There will most likely never be a good answer to this question. I cheekily propose that any n + 1 type be equivalent and that you must name your own when writing an elm app