elm / error-message-catalog

A catalog of broken Elm programs / data to improve error messages
BSD 3-Clause "New" or "Revised" License
173 stars 17 forks source link

Confusing error message when using Set.fromList in a context expecting Dict #272

Closed nonpop closed 5 years ago

nonpop commented 5 years ago

Trying to compile this

module SSCCE exposing (sscce)

import Dict
import Set

sscce : Dict.Dict Int {}
sscce =
    Set.fromList [ ( 0, {} ) ]

causes the following error message:

-- TYPE MISMATCH ------------------------------------------------- src/SSCCE.elm

The 1st argument to `fromList` is not what I expect:

9|     Set.fromList [ ( 0, {} ) ]
                    ^^^^^^^^^^^^^
This argument is a list of type:

    List ( number, {} )

But `fromList` needs the 1st argument to be:

    List ( number, {} )

Replacing the {} type with String and giving a string argument gives the helpful error:

-- TYPE MISMATCH ------------------------------------------------- src/SSCCE.elm

Something is off with the body of the `sscce` definition:

9|     Set.fromList [ ( 0, "zero" ) ]
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This `fromList` call produces:

    Set.Set ( number, String )

But the type annotation on `sscce` says it should be:

    Dict.Dict Int String

EDIT: I just noticed that in the first case Elm actually produces two error messages, including the helpful one.

evancz commented 5 years ago

I made a fix in https://github.com/elm/compiler/commit/545b1784695500e822c2d044b6b5ed2ab6689552, so my development build is now producing:

-- TYPE MISMATCH ------------------------------------------------------ temp.elm

Something is off with the body of the `sscce` definition:

7|     Set.fromList [ ( 0, {} ) ]
       ^^^^^^^^^^^^^^^^^^^^^^^^^^
This `fromList` call produces:

    Set.Set comparable

But the type annotation on `sscce` says it should be:

    Dict.Dict Int {}

-- TYPE MISMATCH ------------------------------------------------------ temp.elm

The 1st argument to `fromList` is not what I expect:

7|     Set.fromList [ ( 0, {} ) ]
                    ^^^^^^^^^^^^^
This argument is a list of type:

    List ( number, {} )

But `fromList` needs the 1st argument to be:

    List comparable

Hint: Only ints, floats, chars, strings, lists, and tuples are comparable.

I am going to try to make the hint more specific. I'm hoping it can specifically mention that records are not comparable, but I'm not sure if it'll be doable!

evancz commented 5 years ago

I tried making the hint really extra specific, but I ended up needing to rewrite some code that would be a bit too risky to change this close to a release. I ended up with some logic that should improve the hints on comparable clashes, but not in cases where a comparable constraint is having trouble with a type within a list or tuple.

Anyway, thank you for reporting the error here!