Scala 3 原生 FunctionK
可以跑的源码在这里 👉 https://github.com/jcouyang/meow
Scala 2
没有 FunctionK 所以我们需要使用 Cats 的 FunctionK 来做一些事情. 当 FunctionK[F, G] 的 F 和 G 都是 Functor 时, FunctionK 是 F ~> G 的自然变换.
比如:
import cats.~>
def tupledOptionToList[B,C](a: (Option[B], Option[C]), fnk: Option ~> List): (List[B], List[C])
至于为什么不能直接用普通类型为 Option[A] => List[A]
的函数而要用 FunctionK 呢? 请看 Rank-N types.
Scala 3
在 Dotty 中, 已经实现了 Rank N Types, 叫 Polymorphic function types, 就可以很轻松的定义出 ~>
:
// kind * -> *
// FunctionK (* -> *) -> (* -> *)
type ~>[F[_],G[_]] = [A] => F[A] => G[A]
object Main {
// rank 2 type (forall a. Option a -> List a)
val optionToList: Option ~> List = [A] => (a: Option[A]) => a.toList
// forall b c. (Option b, Option c) -> (forall a. Option a -> List a) -> (List b, List c)
def tupledOptionToList[B,C](a: (Option[B], Option[C]), fnk: Option ~> List): (List[B], List[C]) =
(fnk(a._1), fnk(a._2))
def main(args: Array[String]): Unit = {
println(
tupledOptionToList((Some(1), Some("2")), optionToList)
)
}
}
不需任何cats, 是可以完美编译运行的.
不信? 可以自己在 scastie 上试试: https://scastie.scala-lang.org/jcouyang/W5jIXajVTU64g8KZe8V7Kw/9
Footnotes:
1
当 FunctionK[F, G] 的 F 和 G 都是 Functor 时, FunctionK 是 F ~> G 的自然变换.