我有以下仿函数定义
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
object ListFunctor extends Functor[List] { //
def map[A, B](f: A => B)(data: List[A]): List[B] = data map f
}
在scala中, F
是一个集合类型很常见,例如List,Seq,Option,我会问为什么Functor必须是更高的kinded类型,类型参数 F
的真正含义是什么?
2 回答
Functor
必须是更高的kinded,因为我们想要抽象一个类型参数,它本身采用一个类型参数(我们称之为类型构造函数,将Functor[List]
视为具体示例) .Functor
处理的类型类型称为"first order kinds",其类型为* -> *
. 当您查看Functor
的具体实例时,您会看到我们不提供内部类型参数 . 例如,当您为示例中的List
定义仿函数时,将其定义为Functor[List]
. 我们不是为正确的类型(即List[Int]
)创建一个仿函数,而是为List
中包含的任何类型 . 这种抽象带来了巨大的力量,因为你可以将它用于任何适当的List
类型(种类*),无论是List[String]
,List[Int]
等 .我总是喜欢参考Adriaan Moore在他的论文“更高级的Genrics”中绘制的图像:
F
的唯一目的是与Functor
的实施者定义 Contract . 通过F
的签名,我们可以推断出Functor
期望的类型 . 当我们看到它有一个"placeholder"([_]
)时,按惯例,我们知道这意味着F
应该采用单个类型参数 . 如果我们考虑采用单个类型参数的所有类型,我们可以看到有很多,例如List
,Option
,Try
,Future
,Task
等 .有关更高通道类型的更广泛说明,请参阅What is a higher kinded type in Scala?
我的回答有点不同 .
Functor
签名中存在(较高通道)类型参数F[_]
意味着Functor
是类型类 . Typeclasses是一种Scala功能,允许用户在不修改现有类型的情况下添加功能 . 所以Functor[F[_]]
这里不是单一类型,而是许多其他类型的蓝图 . 或者,换句话说,它不是单一类型,而是一类类型,因此单词"typeclass" .现在创建一个具体的仿函数,例如列表的仿函数,需要将该具体类型作为类型参数传递给该蓝图,如果您愿意,该具体类型本身必须具有一个类型参数,通过仿函数的数学定义 . 这是
Functor
签名中的高级类型F[_]
意味着什么 .