I’m teaching PureScript at work and am almost done writing a Functional Programming book that uses PureScript and the one thing that’s really hard to explain is how to interpret the Type Mismatch error message.
Currently it say, that it could not match Type A with Type B. It’s not clear which Type it found and which Type it was expecting to find.
Basically, my suggestion is to make the error message more like Haskell’s where it explicitly states that it ENCOUNTERED Type A but was EXPECTING Type B.
This small change would make it so much easier for students to understand where they went wrong, not to mention, everyday PureScript programmers who have to stop and remember that the first Type is what it encountered and the second Type is what it expected to find.
I don’t think that’s possible (or it might be very difficult to do well). PureScript uses a bi-directional type checker. I believe there’s an issue for this somewhere on the PS repo.
It absolutely is possible to have better errors. Bidirectional type checking actually makes this easier, but the compiler makes no effort to track the provenance of checking/inferring during unification except in the internal stack it keeps. Right now it’s just two types that disagree. If you look at the stack print out (all the stuff below the main error), you will see while checking that ... is equal to .... It is largely safe (for this use case at least) to assume that the type you are checking is what’s encountered/actual, and the type you are checking against is expected.
It’s true that there are often philosophical questions about expected vs actual, but I don’t think those matter much in practice, since it gets it correct the vast majority of the time. You just end up assuming that a written type signature is the tie breaker.
Yeah I definitely agree with @natefaubion here - error messages could definitely be a lot better in many ways (including the subject of this thread). It’s just going to require some effort - it’s probably the thing I would spend the most time on if I were able to dedicate more time to PureScript. I have thought for a while that it would be good to have an error message catalog like Elm had to see if we can spot patterns and opportunities for improvements.
Not only would language adoption be greatly improved by better error messages, but the overall day-to-day experience would be greatly improved for everyone. This particular error is probably the most commonly encountered one and even if this were the only one improved upon in the short-term, a lot of mileage would still be gained.
I think error message improvements are generally going to be some of the more demanding tasks as far as compiler work goes. You need to understand the type checker well enough to imagine the whole range of situations in which a particular error might arise, otherwise you’re likely to improve the message in one specific case but make it worse in other cases. In terms of first contributions, I think improving error messages inside the compiler is not likely to be suitable, but setting up an error message catalog that’s easy to contribute to is likely to be more straightforward and would definitely be a good step.
I completely agree; I think error message improvements would be one of the most valuable things we could get right now. I don’t think there’s really any disagreement that it would be worthwhile; the reason there hasn’t been much movement on this front is that it’s hard.
Yes, I’m thinking it would be good to have a collection of PureScript programs which don’t compile and which produce poor error messages. It wouldn’t be for documentation, it would be for analysis in order to identify if there are patterns about which programs are likely to produce poor error messages, or to see if we can work out the specific ways in which error messages are lacking which are most likely to confuse people. I’m imagining that if someone gets an error message they don’t understand, they would be encouraged to submit their code to this collection, and then we would have a CI job or something to attempt to compile it and print the error message, and perhaps compare error messages across compiler versions. In particular this collection would be a good place to put broken code which is unsuitable for inclusion in the existing errors directory of the documentation repo because it’s too complex and there’s too much stuff in there which isn’t strictly relevant to the error (which is almost always the case with real code). This idea has been used by Elm in the past: it’s mentioned a couple of times in https://elm-lang.org/news/the-syntax-cliff.
Potential problems with this are that it might be too awkward to get code to a point where it’s submittable to the collection if it depends on lots of other project-local code, or if it’s proprietary and the would-be submitter can’t share it, or that other breaking changes in the language or libraries would mean that the code would require upkeep over time.
One way to avoid the need for a lot of maintenance is not allowing any packages other than a few core ones, such as prelude, maybe, and arrays. This way, the programs will need minimal maintenance at worst, and no maintenance at best. How does this sound?
That does reduce the number of submittable examples quite considerably, though. I feel like the most awkward errors in practice are usually those that involve more dependencies with more complex APIs.