-
Notifications
You must be signed in to change notification settings - Fork 454
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 TraverseFilter #255
Add TraverseFilter #255
Conversation
Law("TraverseFilter Laws: Identity", { identityTraverseFilter(TF, GA, cf, EQ) }) | ||
) | ||
|
||
//def traverseIdentity[A, B](fa: F[A], f: A => B): IsEq[F[B]] = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔥
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the latest commits this is already removed 👍
//} | ||
|
||
|
||
// external laws: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔥
object TraverseFilterLaws { | ||
|
||
inline fun <reified F> laws(TF: TraverseFilter<F> = traverseFilter<F>(), GA: Applicative<F> = applicative<F>(), crossinline cf: (Int) -> HK<F, Int>, EQ: Eq<HK<F, Int>>): List<Law> = | ||
TraverseLaws.laws(TF, GA, cf, EQ) + FunctorLaws.laws(GA, cf, EQ) + listOf( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The traverse laws already include the functor laws so no need to add them here again or tests will run twice
@@ -16,6 +17,9 @@ interface ConstInstances<A> : | |||
|
|||
override fun <T, U> foldR(fa: HK<ConstKindPartial<A>, T>, lb: Eval<U>, f: (T, Eval<U>) -> Eval<U>): Eval<U> = lb | |||
|
|||
override fun <G, T, U> traverseFilter(fa: HK<ConstKindPartial<A>, T>, f: (T) -> HK<G, Option<U>>, GA: Applicative<G>): | |||
HK<G, HK<ConstKindPartial<A>, U>> = fa.ev().traverseFilter(f, GA) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
while method args is ok to take the most generic representation of the HK or Kind aliases in return type we should return the most concrete compatible In this case HK<ConstKindPartial<A>, U>
can just be Const<A, U>
same for all other instance methods, return always the most concrete type so users don't have to use ev()
to extract values from the HK representation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to change also in traverse
method 👍
Codecov Report
@@ Coverage Diff @@
## master #255 +/- ##
=========================================
Coverage ? 43.13%
Complexity ? 327
=========================================
Files ? 152
Lines ? 4055
Branches ? 406
=========================================
Hits ? 1749
Misses ? 2184
Partials ? 122
Continue to review full report at Codecov.
|
@@ -20,6 +20,7 @@ abstract class UnitSpec : StringSpec() { | |||
Option.monad() | |||
Option.foldable() | |||
Option.traverse() | |||
Option.traverseFilter() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's magic!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tonilopezmr this is good to go but you have to update this branch with master and make sure all your declared instances provide both an implicit object and tests as they are now for all instances where we can prove they can be resolved implicitly.
val EQ_ID: Eq<HK<OptionTKindPartial<IdHK>, Int>> = Eq { a, b -> | ||
a.value() == b.value() | ||
} | ||
|
||
val EQ_OPTION = object : Eq<HK<OptionTKindPartial<OptionHK>, Int>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a new, easier constructor. Try Eq { a, b -> a.value() == b.value() }
and let the type inference do the rest!
a.ev().value == b.ev().value | ||
} | ||
|
||
val EQ_NESTED_OPTION = object : Eq<HK<OptionTKindPartial<OptionHK>, HK<OptionTKindPartial<OptionHK>, Int>>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It may be that you could make the three Eq instances into a single method parametrized in T.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have added
fun <T> EQ(): Eq<T> = Eq { a, b ->
a.value() == b.value()
}
but it doesn't work
kategory/kategory-core/src/test/kotlin/kategory/data/OptionTTest.kt: (12, 24): Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
public fun <A, T> ConstKind<???, ???> /* = HK<HK<ConstHK, ???>, ???> */.value(): ??? defined in kategory
public fun <A> IdKind<???> /* = HK<IdHK, ???> */.value(): ??? defined in kategory
public inline fun <F, A> OptionTKind<???, ???> /* = HK<HK<OptionTHK, ???>, ???> */.value(): HK<???, Option<???>> defined in kategory
public inline fun <F, W, A> WriterTKind<???, ???, ???> /* = HK<HK2<[ERROR : Unknown type parameter 3], [ERROR : Unknown type parameter 4], [ERROR : Unknown type parameter 5]> /* = HK<HK<WriterTHK, ???>, ???> */, ???> */.value(): HK<???, Tuple2<???, ???>> defined in kategory
I don't know why ヽ(。_°)ノ
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It has to be Eq<HK<OptionTKindPartial>. Let's chat about why in Slack.
) | ||
|
||
inline fun <reified F> identityTraverseFilter(FT: TraverseFilter<F>, GA: Applicative<F> = applicative<F>(), crossinline cf: (Int) -> HK<F, Int>, EQ: Eq<HK<F, HK<F, Int>>> = Eq.any()) = | ||
forAll(genConstructor(genIntSmall(), cf), { fa: HK<F, Int> -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you have an applicative of F you shouldn't need a constructor function: genApplicative() does the same job!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice PR! One small tweak to the tests and we're good to go!
Co-authored-by: Rachel M. Carmena <[email protected]>
Fixes: #253
Added
TraverseFilter
andTraverseFilterLaws
Added
OptionTTraverseFilter
,ComposedTraverseFilter
Added
TraverseFilter
andTraverseFilterLaws
forOptionT
,Option
andConst