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 TraverseFilter #255

Merged
merged 29 commits into from
Sep 15, 2017
Merged

Add TraverseFilter #255

merged 29 commits into from
Sep 15, 2017

Conversation

tonilopezmr
Copy link
Member

@tonilopezmr tonilopezmr commented Sep 5, 2017

Fixes: #253

Added TraverseFilter and TraverseFilterLaws
Added OptionTTraverseFilter, ComposedTraverseFilter
Added TraverseFilter and TraverseFilterLaws for OptionT, Option and Const

@tonilopezmr tonilopezmr self-assigned this Sep 5, 2017
@tonilopezmr tonilopezmr requested a review from raulraja September 5, 2017 13:58
@raulraja raulraja mentioned this pull request Sep 5, 2017
54 tasks
Law("TraverseFilter Laws: Identity", { identityTraverseFilter(TF, GA, cf, EQ) })
)

//def traverseIdentity[A, B](fa: F[A], f: A => B): IsEq[F[B]] = {
Copy link
Member

Choose a reason for hiding this comment

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

🔥

Copy link
Member Author

@tonilopezmr tonilopezmr Sep 5, 2017

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:
Copy link
Member

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(
Copy link
Member

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)
Copy link
Member

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.

Copy link
Member Author

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-io
Copy link

codecov-io commented Sep 5, 2017

Codecov Report

❗ No coverage uploaded for pull request base (master@c5d26d6). Click here to learn what that means.
The diff coverage is 47.82%.

Impacted file tree graph

@@            Coverage Diff            @@
##             master     #255   +/-   ##
=========================================
  Coverage          ?   43.13%           
  Complexity        ?      327           
=========================================
  Files             ?      152           
  Lines             ?     4055           
  Branches          ?      406           
=========================================
  Hits              ?     1749           
  Misses            ?     2184           
  Partials          ?      122
Impacted Files Coverage Δ Complexity Δ
...c/main/kotlin/kategory/instances/ConstInstances.kt 68.42% <100%> (ø) 0 <0> (?)
...main/kotlin/kategory/typeclasses/TraverseFilter.kt 20% <20%> (ø) 0 <0> (?)
...egory-core/src/main/kotlin/kategory/data/Option.kt 55.76% <50%> (ø) 8 <1> (?)
...tegory-core/src/main/kotlin/kategory/data/Const.kt 53.33% <50%> (ø) 4 <1> (?)
...e/src/main/kotlin/kategory/typeclasses/Composed.kt 68.08% <54.54%> (ø) 0 <0> (?)
...gory-core/src/main/kotlin/kategory/data/OptionT.kt 41.81% <75%> (ø) 8 <2> (?)
...main/kotlin/kategory/instances/OptionTInstances.kt 86.95% <83.33%> (ø) 0 <0> (?)
...rc/main/kotlin/kategory/laws/TraverseFilterLaws.kt 9.09% <9.09%> (ø) 1 <1> (?)

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 c5d26d6...dc7be24. Read the comment docs.

@@ -20,6 +20,7 @@ abstract class UnitSpec : StringSpec() {
Option.monad()
Option.foldable()
Option.traverse()
Option.traverseFilter()
Copy link
Member Author

Choose a reason for hiding this comment

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

It's magic!

Copy link
Member

@raulraja raulraja left a 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>> {
Copy link
Member

@pakoito pakoito Sep 14, 2017

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>>> {
Copy link
Member

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.

Copy link
Member Author

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 ヽ(。_°)ノ

Copy link
Member

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> ->
Copy link
Member

@pakoito pakoito Sep 15, 2017

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!

https://github.com/kategory/kategory/blob/master/kategory-test/src/main/kotlin/kategory/generators/Generators.kt#L5

Copy link
Member

@pakoito pakoito left a 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!

@pakoito pakoito merged commit 13319e8 into master Sep 15, 2017
@pakoito pakoito deleted the toni-traversefilter branch September 15, 2017 23:00
rachelcarmena added a commit that referenced this pull request Feb 24, 2021
rachelcarmena added a commit that referenced this pull request Feb 24, 2021
Co-authored-by: Rachel M. Carmena <[email protected]>
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.

4 participants