为什么可以找到树的`Functor` 实例,但不能找到分支或叶子的实例?
Why can find `Functor` instance for Tree but not for Branch or Leaf?
我有以下 Functor 定义:
import cats.Functor
import cats.syntax.functor._
object Theory {
implicit val treeFunctor: Functor[Tree] =
new Functor[Tree] {
def map[A, B](fa: Tree[A])(f: A => B): Tree[B] =
fa match {
case Branch(left, right) =>
Branch(map(left)(f), map(right)(f))
case Leaf(value) =>
Leaf(f(value))
}
}
def main(args: Array[String]): Unit = {
Branch(Leaf(10), Leaf(20)).map(_ * 2)
}
}
对于:
sealed trait Tree[+A]
final case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]
final case class Leaf[A](value: A) extends Tree[A]
为什么编译器会报错:
// <console>:42: error: value map is not a member of wrapper.Branch[
Int]
//
Branch(Leaf(10), Leaf(20)).map(_ * 2)
//
所以我必须创建一个智能构造函数:
object Tree {
def branch[A](left: Tree[A], right: Tree[A]): Tree[A] =
Branch(left, right)
def leaf[A](value: A): Tree[A] =
Leaf(value)
}
在这种情况下什么是智能构造函数?
Functor[F[_]]
在cats
中的声明在F
中是不变的。
因此,Functor[Tree]
既不是 Functor[Branch]
的概括,也不是其特化。这些类型不相关。
您的代码存在以下问题。表达式
Branch(Leaf(10), Leaf(20))
属于 Branch[Int]
类型。当您尝试直接将 .map[X]
应用于它时,您表示您希望获得 Branch[X]
作为结果。但是范围内没有 Functor[Branch]
(并不是说你不能写一个,但就目前而言,有 none)。
为了使用 Functor[Tree]
,您必须向编译器明确表示您希望将此实例视为 Tree[Int]
。铸造会起作用。或者使用隐藏 Branch
并公开 Tree
的自定义工厂方法也可以工作:这就是 "smart" 构造函数正在做的事情。
您可以使用kittens
并实现Branch
和Leaf
的实例,然后可以派生Tree
的实例。
libraryDependencies += "org.typelevel" %% "kittens" % "1.0.0-RC2"
import cats.Functor
import cats.syntax.functor._
sealed trait Tree[+A]
final case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]
final case class Leaf[A](value: A) extends Tree[A]
implicit val treeFunctor: Functor[Tree] = cats.derive.functor[Tree]
implicit val branchFunctor: Functor[Branch] =
new Functor[Branch] {
def map[A, B](fa: Branch[A])(f: A => B): Branch[B] =
fa match {
case Branch(left, right) =>
Branch(left.map(f), right.map(f))
}
}
// or without extension method
// implicit def branchFunctor(implicit treeFunctor: Functor[Tree]): Functor[Branch] =
// new Functor[Branch] {
// def map[A, B](fa: Branch[A])(f: A => B): Branch[B] =
// fa match {
// case Branch(left, right) =>
// Branch(treeFunctor.map(left)(f), treeFunctor.map(right)(f))
// }
// }
implicit val leafFunctor: Functor[Leaf] =
new Functor[Leaf] {
def map[A, B](fa: Leaf[A])(f: A => B): Leaf[B] =
fa match {
case Leaf(value) =>
Leaf(f(value))
}
}
def main(args: Array[String]): Unit = {
(Branch(Leaf(10), Leaf(20)): Tree[Int]).map(_ * 2)
Branch(Leaf(10), Leaf(20)).map(_ * 2)
Leaf(10).map(_ * 2)
}
实际上你可以导出所有三个实例:
implicit val treeFunctor: Functor[Tree] = cats.derive.functor[Tree]
implicit val leafFunctor: Functor[Leaf] = cats.derive.functor[Leaf]
implicit val branchFunctor: Functor[Branch] = cats.derive.functor[Branch]
def main(args: Array[String]): Unit = {
(Branch(Leaf(10), Leaf(20)): Tree[Int]).map(_ * 2)
Branch(Leaf(10), Leaf(20)).map(_ * 2)
Leaf(10).map(_ * 2)
}
我有以下 Functor 定义:
import cats.Functor
import cats.syntax.functor._
object Theory {
implicit val treeFunctor: Functor[Tree] =
new Functor[Tree] {
def map[A, B](fa: Tree[A])(f: A => B): Tree[B] =
fa match {
case Branch(left, right) =>
Branch(map(left)(f), map(right)(f))
case Leaf(value) =>
Leaf(f(value))
}
}
def main(args: Array[String]): Unit = {
Branch(Leaf(10), Leaf(20)).map(_ * 2)
}
}
对于:
sealed trait Tree[+A]
final case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]
final case class Leaf[A](value: A) extends Tree[A]
为什么编译器会报错:
// <console>:42: error: value map is not a member of wrapper.Branch[
Int]
//
Branch(Leaf(10), Leaf(20)).map(_ * 2)
//
所以我必须创建一个智能构造函数:
object Tree {
def branch[A](left: Tree[A], right: Tree[A]): Tree[A] =
Branch(left, right)
def leaf[A](value: A): Tree[A] =
Leaf(value)
}
在这种情况下什么是智能构造函数?
Functor[F[_]]
在cats
中的声明在F
中是不变的。
因此,Functor[Tree]
既不是 Functor[Branch]
的概括,也不是其特化。这些类型不相关。
您的代码存在以下问题。表达式
Branch(Leaf(10), Leaf(20))
属于 Branch[Int]
类型。当您尝试直接将 .map[X]
应用于它时,您表示您希望获得 Branch[X]
作为结果。但是范围内没有 Functor[Branch]
(并不是说你不能写一个,但就目前而言,有 none)。
为了使用 Functor[Tree]
,您必须向编译器明确表示您希望将此实例视为 Tree[Int]
。铸造会起作用。或者使用隐藏 Branch
并公开 Tree
的自定义工厂方法也可以工作:这就是 "smart" 构造函数正在做的事情。
您可以使用kittens
并实现Branch
和Leaf
的实例,然后可以派生Tree
的实例。
libraryDependencies += "org.typelevel" %% "kittens" % "1.0.0-RC2"
import cats.Functor
import cats.syntax.functor._
sealed trait Tree[+A]
final case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]
final case class Leaf[A](value: A) extends Tree[A]
implicit val treeFunctor: Functor[Tree] = cats.derive.functor[Tree]
implicit val branchFunctor: Functor[Branch] =
new Functor[Branch] {
def map[A, B](fa: Branch[A])(f: A => B): Branch[B] =
fa match {
case Branch(left, right) =>
Branch(left.map(f), right.map(f))
}
}
// or without extension method
// implicit def branchFunctor(implicit treeFunctor: Functor[Tree]): Functor[Branch] =
// new Functor[Branch] {
// def map[A, B](fa: Branch[A])(f: A => B): Branch[B] =
// fa match {
// case Branch(left, right) =>
// Branch(treeFunctor.map(left)(f), treeFunctor.map(right)(f))
// }
// }
implicit val leafFunctor: Functor[Leaf] =
new Functor[Leaf] {
def map[A, B](fa: Leaf[A])(f: A => B): Leaf[B] =
fa match {
case Leaf(value) =>
Leaf(f(value))
}
}
def main(args: Array[String]): Unit = {
(Branch(Leaf(10), Leaf(20)): Tree[Int]).map(_ * 2)
Branch(Leaf(10), Leaf(20)).map(_ * 2)
Leaf(10).map(_ * 2)
}
实际上你可以导出所有三个实例:
implicit val treeFunctor: Functor[Tree] = cats.derive.functor[Tree]
implicit val leafFunctor: Functor[Leaf] = cats.derive.functor[Leaf]
implicit val branchFunctor: Functor[Branch] = cats.derive.functor[Branch]
def main(args: Array[String]): Unit = {
(Branch(Leaf(10), Leaf(20)): Tree[Int]).map(_ * 2)
Branch(Leaf(10), Leaf(20)).map(_ * 2)
Leaf(10).map(_ * 2)
}