-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Support lifting polymorphic functions to FunctionK in Scala 3 #3895
Conversation
The CI failure seems to be GH actions playing up. |
class FunctionKLiftSuite extends CatsSuite { | ||
|
||
test("lift a polymorphic function directly") { | ||
val fHeadOption = FunctionK.lift[List, Option]([X] => (_: List[X]).headOption) |
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.
Note that in the future the compiler should support polymorphic sam, so you'll be able to write val fHeadOption: List ~> Option = [X] => (_: List[X]).headOption
(or maybe even = _.headOption
)
* val headOptionK = FunctionK.lift[List, Option]([X] => (_: List[X]).headOption) | ||
* }}} | ||
*/ | ||
def lift[F[_], G[_]](f: [X] => F[X] => G[X]): FunctionK[F, G] = |
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.
This isn't a macro is it? Why the name?
I wonder if there could be a Conversion here so you could use a literal in scala 3 without having to call lift.
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 think it's convenient to put it in this file/class, because it was already present (the Scala 2 side uses it for macros). Ideally it could be renamed something more appropriate.
FTR I personally haven't had a good experiencing using Conversion
on Scala 3, as it needs a feature import to enable implicit conversions. That makes me tend to stay away.
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.
Maybe I'm wrong but it shouldn't need a feature import if the conversion is on the companion object.
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.
Thanks, I tried slapping an implicit
in front of this but actually it doesn't seem to work 🤔
def lift[F[_], G[_]](f: [X] => F[X] => G[X]): FunctionK[F, G] = | |
implicit def lift[F[_], G[_]](f: [X] => F[X] => G[X]): FunctionK[F, G] = |
[error] -- [E007] Type Mismatch Error: /workspace/cats/tests/shared/src/test/scala-3/cats/tests/FunctionKLiftSuite.scala:40:77
[error] 40 | val fHeadOption: FunctionK[List, Option] = [X] => (_: List[X]).headOption
[error] | ^
[error] | Found: [X] => (List[X]) => Option[X]
[error] | Required: cats.arrow.FunctionK[List, Option]
I also tried using given Conversion[...]
but the compiler didn't like that with our current scalacOptions
.
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.
Yeah, it seems this just doesn't work. Maybe worth opening a dotty issue?
//> using scala "3.1.2"
//> using lib "org.typelevel::cats-core::2.7.0"
import cats.arrow.FunctionK
def lift[F[_], G[_]](f: [X] => F[X] => G[X]): FunctionK[F, G] =
new FunctionK[F, G] {
def apply[A](fa: F[A]): G[A] = f(fa)
}
given [F[_], G[_]]: Conversion[[X] => F[X] => G[X], FunctionK[F, G]] = lift(_)
@main def main =
val fHeadOption: FunctionK[List, Option] = [X] => (_: List[X]).headOption
val a = List(1, 2, 3)
assert(fHeadOption(a) == a.headOption)
[error] ./functionk.scala:14:76: Found: [X] => (List[X]) => Option[X]
[error] Required: cats.arrow.FunctionK[List, Option]
[error] val fHeadOption: FunctionK[List, Option] = [X] => (_: List[X]).headOption
[error]
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 think just type inference fails here:
scala> summon[Conversion[[X] => List[X] => Option[X], FunctionK[List, Option]]](using given_Conversion_X_FunctionK)
-- [E007] Type Mismatch Error: -------------------------------------------------
1 |summon[Conversion[[X] => List[X] => Option[X], FunctionK[List, Option]]](using given_Conversion_X_FunctionK)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|Found: Conversion[[X] => (Nothing) => Any, FunctionK[F, G]]
|Required: Conversion[[X] => (List[X]) => Option[X], FunctionK[List, Option]]
|
|where: F is a type variable with constraint <: [_] =>> Any
| G is a type variable with constraint <: [_] =>> Any
longer explanation available when compiling with `-explain`
1 error found
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.
yeah, this seems like maybe it is a bug that could be filed with scala.
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 opened scala/scala3#15276.
@bplommer do you mind fixing this up? My efforts to revive it have fallen short. |
No description provided.