GithubHelp home page GithubHelp logo

checklist's People

Contributors

davegurnell avatar jacoby6000 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

checklist's Issues

Make monadic?

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.

I knew I wasn't the only one that had this idea

hey I just started working on a validation lib as well: https://github.com/amilkov3/validen, however mine involves specifying validations via a simple spec language as opposed to programmatically (though there is a validation AST). i think our libraries would compliment each other well as they currently address separate use cases but share commonalities (ValidatedNel from cats and well a functional approach in general). would you want to collaborate and maybe eventually combine the two?

scalaz support

Hi. Thanks for the great work. I discovered checklist when searching for an alternative for ValidationNel with support for soft errors, which is a very compelling use case.

However my code base is based in scalaz, so I have forked and ported checklist to scalaz in this branch

Would you be interested in this?

Build HLists or tuples for composing outputs

I don't know how to put this in to words, so I'll throw it in an example..

case class AddressInput(house: Option[Int], street: Option[String], street2: Option[String])
case class ValidatedAddress(house: Int, street: String, street2: Option[String])

implicit val checkAddress: Rule[AddressInput, ValidatedAddress]
  Rule[AddressInput]
    .field(_.house)(req andThen gte(1))
    .field(_.street)(req andThen trimString andThen nonEmpty)
    .field(_.street2)(optional(trimString))
    .map { addr => 
      ValidatedAddress(addr.house.get, addr.street.get, addr.street2.get 
    }

Having to use .get in there is pretty unfortunate. If instead running .field would return some sort of RuleBuilder[A, B] where A is the input type, and B is the output type, you could do something like

case class AddressInput(house: Option[Int], street: Option[String], street2: Option[String])
case class ValidatedAddress(house: Int, street: String, street2: Option[String])

implicit val checkAddress: Rule[AddressInput, ValidatedAddress]
  Rule[AddressInput]
    .field(_.house)(req andThen gte(1)) // RuleBuilder[AddressInput, Int :: HNil]
    .field(_.street)(req andThen trimString andThen nonEmpty) // RuleBuilder[AddressInput, Int :: String :: HNil]
    .field(_.street2)(optional(trimString)) // RuleBuilder[AddressInput, Int :: String :: Option[String] :: HNil]
    .build { 
      case street2 :: street :: house :: HNil => ValidatedAddress(street2, street, house) 
    }

This could be expanded upon and you could have the builder function derived from shapeless Generic as well. When working with scalapb especially this feature would be useful. A builder which just returns a Rule[A, A] would also be possible, but I think that the Rule class itself should have a method for running a sanitization and returning the validated (and unsanitized) result.

I'll consider making a PR as a POC sometime soon if I can find time.

Allow the user to customise the Checked type?

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:

  • soft vs hard failures (errors and warnings);
  • annotation of failures with paths.

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.

Parsing Lib Integrations?

I think it'd be very helpful to provide integrations with json/xml/ parsing libs. Ideally we'd provide a function decoder a -> validator a b -> decoder b. This way users can transparently use checklist for validation during parsing.

Example for something like circe:

def validatingDecoder[A, B](
  handleWarnings: (WarningMessages, B) => DecodeResult[B])(
  implicit decoder: Decoder[A], validator: Validator[A, B]
): Decoder[B] = 
  decoder.emap(validator.validate(_).fold(
    handleErrors = validatorErrorToCirceError,
    handleWarnings = handleWarnings,
    handleSuccess = DecodeResult.success(_)
  ))

Custom Checked monad

I think we should change the default semantics of Checked. This thread is intended for that discussion. To provide more detail...

The semantics of Ior allow the user to map on the right hand side, regardless of what values are on the left hand side. Most rules in checklist allow the user to signal errors and retain a value on the right. This gives slightly odd semantics where error handling doesn't fail fast when the programmer expects it to.

@Jacoby6000 provided a workaround for this in #9 by adding "strict mode" checks that return an Ior.left on failure instead of an Ior.both. However, I still think this is too fiddly. IMO a developer should be able to choose failure semantics up front and not have to worry about them afterwards. See #2 for thoughts on allowing abstraction of the Checked type.

Regardless of whether we can abstract over different implementations of Checked, we still need to choose a default failure semantics. These are the properties I believe most developers (myself included) will expect:

  • errors cause fast failure under map and flatMap;
  • errors accumulate (no fast failure) under field and fieldWith
    (and possibly ap and mapN);
  • warnings always accumulate and never cause fast failure;
  • values are retained on the right hand side as long as possible.

The problem with this is that flatMap and ap have inconsistent semantics. This is something that Cats and Scalaz fundamentally avoid. However, I believe that in the case of checklist, a non-rules-compliant custom Checked monad will be a reasonable thing to create.

What do people think? Is this an ok idea? Is it an ok idea if we allow users to swap out Checked for Either or Ior as suggested in #2?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.