我正在经历“ Scala with cats”。在3.5.2(第58页,底部)中有一个示例:
def doMath[F[_]](start: F[Int])(implicit functor: Functor[F]): F[Int] =
start.map(n => n + 1 * 2)
用法非常简单:
import cats.instances.option._ // for Functor
import cats.instances.list._
// for Functor
doMath(Option(20))
// res3: Option[Int] = Some(22)
doMath(List(1, 2, 3))
// res4: List[Int] = List(3, 4, 5)
我应该如何理解方法签名(F[_]
)中的类型构造函数?据说在几页之前,应该提供type参数来创建类型。这里的整个内容(F[_]
是一个类型参数,看起来_
是通配符,以便编译器可以推断F
的类型参数。
答案 0 :(得分:3)
类型构造器F[_]
必须是Functor
类型类的成员。此约束由隐式参数列表施加在F
上
(implicit functor: Functor[F])
整个签名
def doMath[F[_]](start: F[Int])(implicit functor: Functor[F]): F[Int]
可能解释如下
给出属于
F
成员的任何类型构造函数Functor
类型类,则doMath
可以将类型F[Int]
的有效值转换为 类型F[Int]
的另一个有效值。
在这里我使用短语有效值来强调它不是原始类型的值,例如Int
,而是在应用类型构造函数{{1}之后构造的类型的值}来输入参数F
,即Int
。
此外,我在sense of
中使用短语 member组建,参加或有关系
请注意,在这种情况下下划线F[Int]
的使用与推断无关。 _
和F[X]
类型的构造符表示same的含义。在方法签名的其余部分中,任何地方都不会使用类型参数F[_]
,因此,根据惯例,我们使用下划线语法X
。另一约定是在F[_]
中使用小写x
,而不是F[x]
,以强调未使用F[X]
。
实际上x
本身就是一个类型参数,当将类型构造函数F[_]
应用到它上时,我们得到的是 proper 类型Functor
,即使两个{ {1}}和Functor[F]
是类型构造函数,例如
F