Skip to content

Make monadic? #1

Description

@davegurnell

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.

Activity

  1. Jacoby6000 commented on May 16, 2017

    @Jacoby6000
    Collaborator

    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 :)

  2. davegurnell commented on May 16, 2017

    @davegurnell
    OwnerAuthor
  3. Jacoby6000 commented on May 16, 2017

    @Jacoby6000
    Collaborator

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

  4. davegurnell commented on May 21, 2017

    @davegurnell
    OwnerAuthor

    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.

  5. Jacoby6000 commented on May 21, 2017

    @Jacoby6000
    Collaborator

    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.

  6. Jacoby6000 commented on Jun 4, 2017

    @Jacoby6000
    Collaborator

    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

  7. davegurnell commented on Jun 5, 2017

    @davegurnell
    OwnerAuthor
  8. Jacoby6000 commented on Jun 6, 2017

    @Jacoby6000
    Collaborator

    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.

  9. davegurnell commented on Jun 20, 2018

    @davegurnell
    OwnerAuthor

    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.

  10. rpiaggio commented on Jul 24, 2018

    @rpiaggio

    Hi there!

    I have been experimenting with a monadic version of the checklist precursor library ("io-validation") using an approach similar to @Jacoby6000 's #1 (comment).

    (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.

  11. rpiaggio commented on Jul 24, 2018

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

  12. rpiaggio commented on Jul 28, 2018

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

  13. davegurnell commented on Aug 12, 2018

    @davegurnell
    OwnerAuthor
  14. added 13 commits that reference this issue on Aug 16, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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