5 ms·
Many of the error messages become clearer with experience, but this is mostly due to developing an intuition for what is actually wrong with your code based on
by thinkpad20 10y ago
Many of the error messages become clearer with experience, but this is mostly due to developing an intuition for what is actually wrong with your code based on the error message you see, not due to the helpfulness of the error message. Often the actual source of the error is in a different place than what is reported. Consider what happens if you mean to concatenate two strings but forget to put `++` in there:
Prelude> "foo" "bar"
<interactive>:3:1:
Couldn't match expected type ‘[Char] -> t’
with actual type ‘[Char]’
Relevant bindings include it :: t (bound at <interactive>:3:1)
The function ‘"foo"’ is applied to one argument,
but its type ‘[Char]’ has none
In the expression: "foo" "bar"
In an equation for ‘it’: it = "foo" "bar"
Yikes. Even worse, consider a similar situation with numbers:
Prelude> 1 2
<interactive>:2:1:
Non type-variable argument in the constraint: Num (a -> t)
(Use FlexibleContexts to permit this)
When checking that ‘it’ has the inferred type
it :: forall a t. (Num a, Num (a -> t)) => t
Also the parser errors in Haskell are terrible. That the community has so long put up with "parse error (possibly incorrect indentation or mismatched brackets)" is a marvel to me, and is one of the most irritating errors to fix because of the (at least apparent) simplicity of improving it.
- HelloNurse 10y agoThe first error message is good: it helpfully includes the exact expression that craps out, and it means, matching intuition about how Haskell should be compiled, that the expression "foo" "bar" could only make sense if "foo" were a function from [Char] (i.e. the type of "bar") to some type t, but unfortunately "foo" is a [Char]: everyone should understand it easily, even if gratuitously introducing other names (it and its type t) and details about the compiler making up type equations is highly inelegant. The second error message, on the other hand, proves that the first one is a lucky accident.
- AlexCoventry 10y agoEverything you say is true, but it took me about 90s of staring at the Haskell error before I parsed out exactly what it was objecting to, even though I knew exactly how the code was broken. Whereas it took me no discernible time to understand the Elm error messages. Some of it could be that parsing the Haskell message primed me for the Elm message, but it doesn't seem that way to me.
- MustardTiger 10y ago>The second error message, on the other hand, proves that the first one is a lucky accident. No, the second error message just shows that there's more options there so the error message is vague and not very helpful. The first one is not an accident, it is the standard type mismatch error.
- HelloNurse 10y agoMy point is that 1 2 should give the same type of error message as "foo" "bar", because it is the same kind of error (1 isn't a function with one or more arguments). The compiler exposes that when numbers are involved it attempts (and fails) some fancy and unexpected reasoning involving forall, while with plain type constructors like [Char] it attempts (and fails) straightforward and intelligible pattern matching. Figuring out the type of 1 and 2 might be more difficult than figuring out the type of "foo" and "bar", but the special rules should be hidden: a compiler that cares about practical usage would provide unified and clear error messages, possibly listing sets of alternative types it was unable to choose from.
- MustardTiger 10y ago>My point is that 1 2 should give the same type of error message as "foo" "bar", because it is the same kind of error And my point is that no it should not. "1 2" is more ambiguous, it could be more things, hence there is a more ambiguous error message.
- the_af 10y agoNot saying many Haskell compiler errors are obscure, especially for the uninitiated, but the particular error you picked as your first example is perfectly clear. Haskell is telling you 'you tried to apply a string literal to an argument as if it were a function, but it's not! It's a string literal. By the way, the string I'm talking about is "foo", which you tried to apply to "bar" in the expression "foo bar"'. Yikes? It seems pretty helpful to me :) Your second example is better, though.
- IanCal 10y agoThe output contains all you need, yes, but it would be nice if what you typed was added to the output. You wrote out a much more user friendly version. Someone posted the output from Elm, which does this: https://news.ycombinator.com/item?id=11848467 https://news.ycombinator.com/item?id=11848467 Edit: checkout the elm error message page here http://elm-lang.org/blog/compilers-as-assistants http://elm-lang.org/blog/compilers-as-assistants
- the_af 10y agoAgreed, Elm in these two examples is way nicer! It doesn't add information, but it presents it in a beginner-friendly way, which is commendable. However, I'm left wondering... Elm seems to be using hardcoded knowledge about commonly used types such as strings and numbers in order to improve its error messages (I wonder why Haskell doesn't, by the way). What happens in Elm when an error occurs with more complex, user-defined types and operations?
- masklinn 10y agoIn the "+" case, only the final hint is type-specific. The first error is kind-of type-specific but only distinguishes functions and non-functions.
- IanCal 10y agoIt looks like it's only the specific hint at the bottom that requires any custom knowledge about the types themselves. If you're interested, there were a couple more examples shown elsewhere in this thread: http://elm-lang.org/blog/compiler-errors-for-humans http://elm-lang.org/blog/compiler-errors-for-humans (an older version it seems) https://twitter.com/st58/status/732908457217531904 https://twitter.com/st58/status/732908457217531904 https://twitter.com/GregorySchier/status/732830868562182144 https://twitter.com/GregorySchier/status/732830868562182144 Something I've just found is that the errors can also be output in a nice machine readable format, so the suggested fixes can be read in by your editor plugin. And finally, this is wonderful, a specific repo for code that causes error messages and a request for people to submit error messages that are confusing: https://github.com/elm-lang/error-message-catalog https://github.com/elm-lang/error-message-catalog
- ob 10y agoAnd that is exactly why people love Elm: > "foo" "bar" -- TYPE MISMATCH --------------------------------------------- repl-temp-000.elm You are giving an argument to something that is not a function! 3| "foo" "bar" ^^^^^ Maybe you forgot some parentheses? Or a comma? Also > "foo" + "bar" -- TYPE MISMATCH --------------------------------------------- repl-temp-000.elm The left argument of (+) is causing a type mismatch. 3| "foo" + "bar" ^^^^^ (+) is expecting the left argument to be a: number But the left argument is: String Hint: To append strings in Elm, you need to use the (++) operator, not (+). <http://package.elm-lang.org/packages/elm-lang/core/latest/Basics#++>
- the_af 10y agoInteresting! Thanks for the example. How do compiler errors look in Elm with generic functions involved, about which the compiler doesn't have any helpful hardcoded knowledge? (I.e. no "+" or strings involved).
- elros 10y agoIf you mean typeclasses, Elm doesn't have them. Regarding hardcoded messages, there's been at some point talk in the community regarding allowing library authors to have some sort of hook to compiler that would make it possible to customize specific error messages along with a package.
- elros 10y agoIf you mean typeclasses, Elm doesn't have them. Regarding hardcoded messages, there's been at some point talk in the community regarding allowing library authors to have some sort of hook to compiler that would make it possible to customize specific error messages along with a package.