HOME | EDIT | RSS | INDEX | ABOUT | GITHUB

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 的自然变换.