Skip to content

Improve Error messages #129

@ktec

Description

@ktec

Currently the error messages look something like this:

iex> AgeCheck.user_older_than?("foobar", 42)
** (TypeCheck.TypeError) At lib/type_check_example.ex:28:
The call to `user_older_than?/2` failed,
because parameter no. 1 does not adhere to the spec `%User{age: integer(), name: binary()}`.
Rather, its value is: `"foobar"`.
Details:
  The call `user_older_than?("foobar", 42)` 
  does not adhere to spec `user_older_than?(%User{age: integer(), name: binary()},  integer()) :: boolean()`. Reason:
    parameter no. 1:
      `"foobar"` does not check against `%User{age: integer(), name: binary()}`. Reason:
        `"foobar"` is not a map.
    (type_check_example 0.1.0) lib/type_check_example.ex:28: AgeCheck.user_older_than?/2

There is considerable duplication here which can be confusing for new users at least. I wonder if we could improve this somehow.

I guess the tasks here are:

  1. Decide on how to reduce the duplication and then improve the default formatter
  2. Define a "consise formatter" which presents the same info with brevity

I'll start the discussion using the example above.

This provides me information about the type mismatch:

iex> AgeCheck.user_older_than?("foobar", 42)
** (TypeCheck.TypeError) At lib/type_check_example.ex:28:
The call to `user_older_than?/2` failed,
because parameter no. 1 does not adhere to the spec `%User{age: integer(), name: binary()}`.
Rather, its value is: `"foobar"`.

This tells me the same thing, with the following additional information:

  • a spec of the function
  • a more complete location of the function (eg. includes the app and module)
  • that "foobar" is not a map
Details:
  The call `user_older_than?("foobar", 42)` 
  does not adhere to spec `user_older_than?(%User{age: integer(), name: binary()},  integer()) :: boolean()`. Reason:
    parameter no. 1:
      `"foobar"` does not check against `%User{age: integer(), name: binary()}`. Reason:
        `"foobar"` is not a map.
    (type_check_example 0.1.0) lib/type_check_example.ex:28: AgeCheck.user_older_than?/2

I don't know the default formatter well enough to suggest what's possible, but perhaps I can suggest something (slightly influenced by elm errors):

iex> AgeCheck.user_older_than?("foobar", 42)
** (TypeCheck.TypeError) At lib/type_check_example.ex:28:
The call to `user_older_than?/2` failed, because the 1st parameter does not adhere to the spec;

    user_older_than?(%User{age: integer(), name: binary()},  integer()) :: boolean()
                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

You have given the value:

                          "foobar"

But a value of the following type is required:

                          `%User{age: integer(), name: binary()}`

Details:
  reason: "is not a map"
  (type_check_example 0.1.0) lib/type_check_example.ex:28: AgeCheck.user_older_than?/2

I know the "details" section bounces down the types to get to the error, so it might be that this just doesn't work, but maybe this will start the discussion.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions