Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add .validate method for refined companions #382

Merged
merged 4 commits into from
Dec 21, 2017

Conversation

howyp
Copy link
Contributor

@howyp howyp commented Dec 20, 2017

Now we have 'companion' objects for refined types, I thought it would be nice to have a neat way to refine to cat's Validated type.

It always uses NonEmptyList on the error side at the moment. I guessed that this is what people will use 90% time but if we think there will also be need for using List or even List Refined Not[Empty] then I we could support that too?

@codecov
Copy link

codecov bot commented Dec 20, 2017

Codecov Report

Merging #382 into master will increase coverage by 0.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff            @@
##           master    #382      +/-   ##
=========================================
+ Coverage   96.58%   96.6%   +0.01%     
=========================================
  Files          41      42       +1     
  Lines         498     500       +2     
  Branches       11      10       -1     
=========================================
+ Hits          481     483       +2     
  Misses         17      17
Impacted Files Coverage Δ
...ain/scala/eu/timepit/refined/cats/validation.scala 100% <100%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update bdf2d0c...bb93a9d. Read the comment docs.

@fthomas
Copy link
Owner

fthomas commented Dec 20, 2017

Looks great, thanks @howyp!

This would also resolve #75 although that one is about adding a method to RefType. My guess is that companions of refined types will replace the RefType.applyRef, refineV and similar methods in the long run so it is okay to have this functionality only on the companion objects.

@@ -11,16 +12,26 @@ class CatsSpec extends Properties("cats") {
val refTypeOrder: Unit = () // shadow the `Order` instance so the `Eq` instance is tested
locally(refTypeOrder) // prevent a "unused" warning

PosInt.unsafeFrom(5) === PosInt.unsafeFrom(5)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm using unsafeFrom in the tests to avoid the overhead of the RefineMacro so that test code compiles faster.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, ok, I'll revert

object validation {
implicit class CatsValidateOps[FTP, T](companion: RefinedTypeOps[FTP, T]) {
def validate(value: T): ValidatedNel[String, FTP] =
Validated.fromEither(companion.from(value)).leftMap(NonEmptyList.one)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a toValidatedNel on Cats' EitherSyntax which would allow us to just write companion.from(value).toValidatedNel here.

@fthomas
Copy link
Owner

fthomas commented Dec 20, 2017

I'm totally fine with using ValidatedNel here. It is probably the predominant data type for error accumulation in the Cats ecosystem, so I don't see the need to deviate from that.

@howyp
Copy link
Contributor Author

howyp commented Dec 20, 2017

Not sure about packaging here - do we need a .syntax as well as a =.validation one? Might be overkill

@fthomas
Copy link
Owner

fthomas commented Dec 20, 2017

I'm not sure if I like d59f2d8. It adds a validate extension to any type and I find such extensions always strange. I would be okay if we only supply the validate method for companions and that is the only way to refine values with Validated.
I know that the library currently has more than one way to do things and RefType is one of the worst contender in this regard. I think in the future I'd like to reduce the surface area of refined's API to make the library simpler.

Regarding syntax vs. validation. I think I like syntax more than validation. It would allow us to maybe add more extension methods that are not related to Validated to the companions.

@kusamakura
Copy link
Contributor

How about some scalaz love? ;) I can take it up if you want, @howyp.

@fthomas
Copy link
Owner

fthomas commented Dec 21, 2017

Adding this functionality to the Scalaz module would be nice too. I would prefer a separate PR for that.

@kusamakura
Copy link
Contributor

kusamakura commented Dec 21, 2017

@fthomas Alright, I'll graft the code from this one into the scalaz module.

@howyp
Copy link
Contributor Author

howyp commented Dec 21, 2017

I can understand why you might feel hesitant about having an operator on anything (though it would only work on types which have a matching refined predicate). It seemed to me to be quite a 'cats' way of doing things - in the style of say .valid[B]. The alternative is to support something like:

import validation._
val myInt = 5
validate[Positive](myInt)

Would you prefer that for the moment?

My motivation was to provide symmetrical support for cases where you haven't defined a full refined type/don't want to create companion objects, but just want to be able to apply a predicate to a raw type. I agree it would be good to distill the API surface of Refined, and that standardising on companion objects for refined types is a great way to go. But only providing second-class support for ad-hoc refinements via a predicate seems a shame to me.

Perhaps how to reduce the surface of the API would be best discussed in a new issue?

@kusamakura
Copy link
Contributor

@howyp I think validate[Positive](myInt) would just be refineV[Positive](myInt).toValidatedNel. On the other hand, the companion method is nice.

@howyp
Copy link
Contributor Author

howyp commented Dec 21, 2017

Ok, I've dropped the 10.validate[Positive] syntax

@fthomas
Copy link
Owner

fthomas commented Dec 21, 2017

Ok, merging now. Thanks again @howyp!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants