davegurnell / checklist

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

Make monadic? #1

Open davegurnell opened 7 years ago

davegurnell commented 7 years ago

It's common for some validation rules to be performed against a database (e.g. duplicate checking). Checklist could handle this in one of two ways: either require the user to load related data before running the tests (dodging the issue) or weaving a monad like DBIO in amongst the validation rules.

It may be worth checking rewriting Rule[A, B] as Rule[F[_]: Monad, A, B] to see if this produces something usable.

Jacoby6000 commented 7 years ago

Has any work toward this been done? I can look in to exploring this, but I wouldn't want to duplicate work if you've already made some headway.

I wonder if it would be better to leave Rule as is, and then also have a RuleT as a monad transformer.

I wonder how this will affect composition of rules in general, though.

The good of RuleT

Considerations of RuleT

I think Monad transormers work here.

I'm mostly thinking aloud. trying to get discussion going :)

davegurnell commented 7 years ago

Hi Jacob,

No. I'm not currently working on this. I have started a project using Checklist, however, so I will be looking to implement duplicate checks on a database at some point in the near future.

Have you thought about what kind of approach you'd take for this? I haven't settled on an implementation in my thoughts yet.

Best regards, Dave On Tue, 16 May 2017 at 20:48, Jacob Barber notifications@github.com wrote:

Has any work toward this been done? I can look in to exploring this, but I wouldn't want to duplicate work if you've already made some headway.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/davegurnell/checklist/issues/1#issuecomment-301895082, or mute the thread https://github.com/notifications/unsubscribe-auth/AAOI59h07dM66bns2m5wTbPv3kFHhGKbks5r6f2PgaJpZM4Mk4-N .

Jacoby6000 commented 7 years ago

Heh, I did some heavy editing after you got that email, I put in some details about what I'm considering above :)

davegurnell commented 7 years ago

Your approach sounds reasonable to me. I wonder if we're stumbling towards a common functional abstraction. Kleisli seems pretty similar, for example. I guess the difference is in the combinator API we're defining in Checklist.

Jacoby6000 commented 7 years ago

I had considered Kleisli; the main problem that comes with that, is A => F[B] may not be sufficient. I can imagine situations where you might need A => F[A] and then F[A] => F[B].... but now as I'm typing this, I realize that's just Kleisli[F[_], A, A].map[B].

I think rule as a whole might just be

type RuleF[F[_], A, B] = Kleisli[F, A, ValidationMessage Ior B]
type Rule[A, B] = RuleF[Id, A, B]

But with combinators. I'll try to work with this idea and see where it goes.

Tl;dr I think you're right.

Jacoby6000 commented 7 years ago

Switching to a Kleisli based encoding has caused lots of problems. None of the functions like map, flatMap, pure, andThen, or any methods that overlap with kleisli (besides contramap) really behave the way users would expect them to. I think it makes sense to go the RuleT route, where you have a standard Rule encoding, and then a MonadTransformer encoding. It is possible to encode all Rules as RuleT, but this can get clunky for people who don't need the extra abstraction.

The work I did can be found here if you're interested (it doesn't quite compile yet) https://github.com/Jacoby6000/checklist/tree/failed/kleisli-encoding

davegurnell commented 7 years ago

Fair enough -- my experiences with Kleisli have been similar. Thanks for your efforts!

I think you're right that the RuleT approach is worth looking into. I may have time to hack on something this weekend. Let me know if you start a branch along those lines!

On Mon, Jun 5, 2017 at 12:01 AM Jacob Barber notifications@github.com wrote:

Switching to a Kleisli based encoding has caused lots of problems. None of the functions like map, flatMap, pure really behave the way users would expect them to. I think it makes sense to go the RuleT route, where you have a standard Rule encoding, and then a MonadTransformer encoding. It is possible to encode all Rules as RuleT, but this can get clunky for people who don't need the extra abstraction.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/davegurnell/checklist/issues/1#issuecomment-306073228, or mute the thread https://github.com/notifications/unsubscribe-auth/AAOI50ASzw0IZUs4eUNwQumBK4Wqh7w_ks5sAzdEgaJpZM4Mk4-N .

Jacoby6000 commented 7 years ago

I'll let you know if I get started on it.

Something I forgot to mention, The Kleisli Encoding works fine for Rule, and behaves exactly how you would expect it to. RuleT is the only thing causing issues with that.

davegurnell commented 6 years ago

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

Users can presumably now leverage methods like Kleisli.mapK to wrap whatever base error handling monad they're using (Ior, for example) in a monad transformer.

rpiaggio commented 6 years ago

Hi there!

I have been experimenting with a monadic version of the checklist precursor library ("io-validation") using an approach similar to @Jacoby6000 's https://github.com/davegurnell/checklist/issues/1#issuecomment-301895082.

(That's the library we actually use, we never got around to migrating to checklist).

It seems to be working so far, so I will attempt to port the changes over to checklist in the next few days and submit a PR.

rpiaggio commented 6 years ago

This is how code looks like in io-validation:

https://github.com/zoepepper/validation/blob/master/shared/src/test/scala/io/underscore/validation/MonadicValidatorSpec.scala

Whenever and, andPrefix, field or fieldSeq is called, natural transformations are applied if an implicit one is in scope.

rpiaggio commented 6 years ago

@davegurnell I'd like to try to port the approach we took in https://github.com/zoepepper/validation to checklist. We ended up requiring the context to be Applicative instead of Monad. This is because, composed validations are independent of each other and by taking the Applicative approach we can run them in parallel (assuming the context does the right thing).

I took a look at the feature/kleisli branch and I think that both approaches can be combined, but I'm not that sure.

Do you think it makes more sense to fork from that branch or start with the develp one? In other words, how confident would you say that the Kleisli approach will make it soon into master?

Also, would you be interested in opening up a Gitter channel for the project so that we can discuss more fluidly?

davegurnell commented 6 years ago

Sorry for the delayed reply. I'm considering the approach in feature/kleisli as an experiment at the moment. The type inference around the check DSL isn't good enough the way it is written.

Please feel to write a proposal based on develop. Do something quick and lightweight if you can so everyone on this ticket can play with it and see how it works.

Cheers, Dave

On Sat, Jul 28, 2018 at 2:28 AM Raúl Piaggio notifications@github.com wrote:

@davegurnell https://github.com/davegurnell I'd like to try to port the approach we took in https://github.com/zoepepper/validation to checklist. We ended up requiring the context to be Applicative instead of Monad. This is because, composed validations are independent of each other and by taking the Applicative approach we can run them in parallel (assuming the context does the right thing).

I took a look at the feature/kleisli branch and I think that both approaches can be combined, but I'm not that sure.

Do you think it makes more sense to fork from that branch or start with the develp one? In other words, how confident would you say that the Kleisli approach will make it soon into master?

Also, would you be interested in opening up a Gitter channel for the project so that we can discuss more fluidly?

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/davegurnell/checklist/issues/1#issuecomment-408573139, or mute the thread https://github.com/notifications/unsubscribe-auth/AAOI59L3FeWmi8TAqNZioMiJCpOUXdAXks5uK74jgaJpZM4Mk4-N .