davegurnell / checklist

Validation library for Scala.
Apache License 2.0
47 stars 11 forks source link

Allow the user to customise the Checked type? #2

Open davegurnell opened 7 years ago

davegurnell commented 7 years ago

The Checked type is restrictive. It doesn't allow the user to add their own data to error messages. We could consider generalising it to allow more customisation.

Checked essentially encompass two concepts:

We could potentially extract these out into type classes to allow developers to customise the error type. We may need to parameterise the entire rule-definition API by the error type to keep things simple.

davegurnell commented 7 years ago

A relevant extract from a recent email conversation with @ashleymercer:

Would it be worth allowing additional levels of message (debug, info etc) or would that be overkill?

This is one reason to allow people to customise the error types. As long as we support soft and hard errors, we have all of the basic semantics we need for this. Log levels like "debug" and "info" are variants on soft errors; levels like "error" and "fatal" are hard errors.

My first thought is to experiment creating a MonadSoftError type class that extends MonadError and allows the user to raise soft and hard errors. Once this is in place, switching to different error levels is a matter of leftMapping over the resulting Ior.

Cross-referencing this with issue #3, the MonadSoftError type wouldn't have to be a subclass of MonadError---it could be its own thing with implementations in terms of cats.MonadError and scalaz.MonadError. Between the MonadSoftError and PathPrefix type classes and some sort of abstraction over Checked, we'd have the ability to abstract over Cats and Scalaz as well as different error types.

davegurnell commented 6 years ago

I spent a little time on an alternative encoding of Rule based directly on Kleisli. The code is in the feature/kleisli branch.

In this codebase, the checklist.core package is error-handling-monad-independent. Users can integrate it with any monad via a type class (confusingly called Checked). This type class specifies the warning/failure/prefixing behaviour we need to model soft errors and error locations.

I've reimplemented the original semantics of Checklist in the checklist.std.ior object. This reintroduces the original Messages type and provides an implementation of all the basic rules on top of Ior[Messages, A].