roc icon indicating copy to clipboard operation
roc copied to clipboard

request: novice-readable error message for task/function mixups

Open gvwilson opened this issue 1 year ago • 2 comments

Working through the Roc tutorial, I wanted to write a function that printed things, so I tried this:

app "example"
    packages { cli: "https://github.com/roc-lang/basic-cli/releases/download/0.8.1/x8URkvfyi9I0QhmVG98roKBUs_AZRkLFwFJVJ3942YA.tar.br" }
    imports [cli.Stdout]
    provides [main] to cli

oneLine = \{} ->
    Stdout.line "first"

main =
    oneLine

roc dev example.roc produced this:

── TYPE MISMATCH in ....1/x8URkvfyi9I0QhmVG98roKBUs_AZRkLFwFJVJ3942YA/main.roc ─

Something is off with the type annotation of the main required symbol:

2│      requires {} { main : Task {} I32 }
                             ^^^^^^^^^^^

This #UserApp.main value is a:

    ({}a -> Task.Task {} *)

But the type annotation on main says it should be:

    InternalTask.Task {} I32

Tip: Type comparisons between an opaque type are only ever equal if
both types are the same opaque type. Did you mean to create an opaque
type by wrapping it? If I have an opaque type Age := U32 I can create
an instance of this opaque type by doing @Age 23.


── TYPE MISMATCH in ....1/x8URkvfyi9I0QhmVG98roKBUs_AZRkLFwFJVJ3942YA/main.roc ─

Something is off with the body of the mainForHost definition:

26│  mainForHost : Task {} I32 as Fx
27│  mainForHost = main
                   ^^^^

This #UserApp.main value is a:

    ({}a -> Task.Task {} *)

But the type annotation on mainForHost says it should be:

    InternalTask.Task {} I32

Tip: Type comparisons between an opaque type are only ever equal if
both types are the same opaque type. Did you mean to create an opaque
type by wrapping it? If I have an opaque type Age := U32 I can create
an instance of this opaque type by doing @Age 23.

────────────────────────────────────────────────────────────────────────────────

2 errors and 0 warnings found in 25 ms.

You can run the program anyway with roc run example.roc

I believe a lot of novices will assume Stdout.line is Roc's equivalent of print and will then put it in their functions. They won't yet have seen tasks, so the error message above will be incomprehensible. (I had to read quite far ahead in the Roc tutorial and look at a couple of examples in order to start to understand the problem.) While I don't often ask for error messages to be shortened, I think this might be a good candidate. Alternatively, can some other form of output be introduced earlier so that people don't even try to do what I did?

gvwilson avatar Mar 12 '24 11:03 gvwilson

Thanks @gvwilson, this is great feedback :)

I've talked about a tool to make it easier for beginners and novices to prevent these types of errors on zulip. What do you think about a tool like that? If it works well we can try to include it in the compiler.

Anton-4 avatar Mar 12 '24 13:03 Anton-4

Added a note on zulip: "I can see the value of the tool that @Anton-4 suggests, but I think that better/slimmer error messages should be the priority. In particular, I think what I'm seeing (as a novice) is cascading error messages: if there's a way to say, "we spotted four other problems but we think they're all related to the one we showed you first", that would be very helpful for newcomers."

gvwilson avatar Mar 12 '24 15:03 gvwilson

Purity inference is totally changing the way that effects are called, which will remove this sort of task/function mixup. (That's one of the reasons we're making such a big change to the language!) So I'm closing this issue as won't do.

skyqrose avatar Nov 23 '24 19:11 skyqrose