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

Deprecate Map.kt traverse & niche signatures, hygiene & bindAll #2971

Merged
merged 10 commits into from
Mar 24, 2023

Conversation

nomisRev
Copy link
Member

@nomisRev nomisRev commented Mar 9, 2023

No description provided.

@nomisRev nomisRev added the 1.2.0 Tickets belonging to 1.1.2 label Mar 9, 2023
@arrow-kt arrow-kt deleted a comment from rafaparadela Mar 16, 2023
@nomisRev nomisRev marked this pull request as ready for review March 16, 2023 14:51
@nomisRev nomisRev changed the title Deprecate map signatures, and hygiene Deprecate Map.kt traverse & niche signatures, hygiene & bindAll Mar 17, 2023
mapOf("1" to 1, "2" to 2)
.align(mapOf("1" to 1, "2" to 2, "3" to 3)) { (_, a) ->
"$a"
} shouldBe mapOf("1" to "Ior.Both(1, 1)", "2" to Ior.Both(2, 2), "3" to Ior.Right(3))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Shouldn't this code return

mapOf("1" to "Ior.Both(1, 1)", "2" to "Ior.Both(2, 2)", "3" to "Ior.Right(3)")

instead?

Comment on lines 52 to 58
buildMap(size) {
this@zip.forEach { (key, bb) ->
nullable {
put(key, map(key, bb, other[key].bind()))
}
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: bb represents a value of type A. Should we rename it to aa?

Suggested change
buildMap(size) {
this@zip.forEach { (key, bb) ->
nullable {
put(key, map(key, bb, other[key].bind()))
}
}
}
buildMap(size) {
this@zip.forEach { (key, aa) ->
nullable {
put(key, map(key, aa, other[key].bind()))
}
}
}

Comment on lines 236 to +246

@Deprecated(
"Traverse for Either is being deprecated in favor of Either DSL + Map.mapValues.\n$NicheAPI",
ReplaceWith(
"let<Map<K, A>, Either<E, Map<K, B>>> { m -> either<E, Map<K, B>> { m.mapValues<K, A, B> { (_, a) -> f(a).bind<B>() } } }",
"arrow.core.raise.either"
)
)
@OptIn(ExperimentalTypeInference::class)
@OverloadResolutionByLambdaReturnType
public inline fun <K, E, A, B> Map<K, A>.traverse(f: (A) -> Either<E, B>): Either<E, Map<K, B>> {
val acc = mutableMapOf<K, B>()
forEach { (k, v) ->
when (val res = f(v)) {
is Right -> acc[k] = res.value
is Left -> return@traverse res
}
}
return acc.right()
}
public inline fun <K, E, A, B> Map<K, A>.traverse(f: (A) -> Either<E, B>): Either<E, Map<K, B>> =
Copy link
Collaborator

Choose a reason for hiding this comment

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

I've been replacing the use of traverse (i.e. here and it doesn't know how to infer the type of the f function 😞 :

(0..20_000).associateWith { it }.let<Map<Int, Int>, Either<Nothing, Map<Int, Int>>> { m ->
          either {
            m.mapValues<Int, Int, Int> { (_: Int, a: Int) ->
              acc.add(a)
              Either.Right<Any>(a).bind<Int>()
            }
          }
        }

And also suffer the issues if the use of f is using the implicit parameter it. It does no know how to infer types.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, I've seen the issue with Either.Right<Any> in multiple places (in our tests)😞 I think it's due to covariance and Nothing in the data class constructor. I think this is why Kotlin Std always requires specifying the arguments, and Nothing is never used anywhere.

If this constructor was operator fun fun <A, B> Either.Right.Companion.invoke(b: B): Either<A, B> = ... I think it would not have been a problem, but it comes with some other trade-offs like not being able to call ::Right.

That being said, I don't think a lot of people are using this pattern in real code, since traverse with only Right is map without Either.. In case that the compiler can know E and A I don't think this ReplaceWith results in any problems. So maybe we can leave this as best effort?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Sure thing. I think we can leave as it is and be reactive in the case some raises an issue.

@serras serras merged commit f0d5a82 into main Mar 24, 2023
@franciscodr franciscodr deleted the sv-map-deprecation branch March 24, 2023 12:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
1.2.0 Tickets belonging to 1.1.2
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants