checklist icon indicating copy to clipboard operation
checklist copied to clipboard

Make monadic?

Open davegurnell opened this issue 7 years ago • 13 comments

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.

davegurnell avatar Mar 22 '17 08:03 davegurnell

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

  • If RuleT was created, then Rule[A, B] could just be defined as type Rule[A, B] = RuleT[Id, A, B]
  • Rule[A, B] could be lifted in to any Monad[F]. This would mean that all Rules would be composable with any RuleT, or other Rule.

Considerations of RuleT

  • RuleT[F[_], A, B] could not compose with RuleT[G[_], A, C] unless provided a F ~> G, or G ~> F.

I think Monad transormers work here.

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

Jacoby6000 avatar May 16 '17 19:05 Jacoby6000

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 [email protected] 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 .

davegurnell avatar May 16 '17 21:05 davegurnell

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

Jacoby6000 avatar May 16 '17 22:05 Jacoby6000

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.

davegurnell avatar May 21 '17 13:05 davegurnell

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 avatar May 21 '17 17:05 Jacoby6000

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

Jacoby6000 avatar Jun 04 '17 23:06 Jacoby6000

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 [email protected] 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 .

davegurnell avatar Jun 05 '17 08:06 davegurnell

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.

Jacoby6000 avatar Jun 06 '17 16:06 Jacoby6000

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.

davegurnell avatar Jun 20 '18 09:06 davegurnell

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 avatar Jul 24 '18 04:07 rpiaggio

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 avatar Jul 24 '18 22:07 rpiaggio

@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?

rpiaggio avatar Jul 28 '18 01:07 rpiaggio

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 [email protected] 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 .

davegurnell avatar Aug 12 '18 08:08 davegurnell