我正在阅读这本书https://underscore.io/books/scala-with-cats/并尝试了解猫的逆变 在页面68上有一个在Cats
中实现 Contravariant的示例我们可以使用
Contravariant
方法召唤Contravariant.apply
的实例。 Cats为使用的数据类型提供实例 参数,包括Eq
,Show
和Function1
。这是一个例子:
import cats.Contravariant
import cats.Show
import cats.instances.string._
object ContraCats {
val showString = Show[String]
val showSymbol = Contravariant[Show]
.contramap(showString)((sym: Symbol) => s"'${sym.name}'")
def main(args: Array[String]): Unit = {
println(showSymbol.show('dave))
}
}
显示类型类型而不是类型,那么如何创建类型类Contravariant
的类型类Show
的实例?并且Show
不是更高级的类型。
答案 0 :(得分:2)
类型类Show
声明为Show[T]
。
Contravariant
被声明为Contravariant[F[_]]
如果我们这样说
Int
有善意*
List[Int]
有善意*
List
有善意* -> *
Monad
的trait Monad[M[_]]
具有(* -> *) -> *
Show
有善意* -> *
Show[Int]
有善意*
Contravariant
有善意(* -> *) -> *
Contravariant[Show]
有善意*
也就是说,Contravariant
是一个需要* -> *
并生成某种*
的东西的东西。由于Show
属于* -> *
,因此类型Contravariant[Show]
有效。
现在,在您的代码段中,有一个表达式 Contravariant[Show]
。它不是一个类型,不应该与类型构造函数的应用混淆。 Desugared,这件事本质上是
Contravariant.apply[Show](inst)
其中Contravariant
是companion object of trait Contravariant
,inst
是隐式提供的 type Contravariant[Show]
的实例。同样,一切都无缝地融合在一起。
备注命名法。我会说Show
是更高级别的"。它绝不是决定性的,但我喜欢Atlassian Blog [强调和代码缩进矿]中的以下引用:
此外,您可以使用更高级别的类型进行参数化的种类。所以,某些东西不仅可以采用一种类型,而且可以采用本身需要类型参数的东西。一个例子是协变仿函数:Functor [F [_]],它有种类:
((* -> *) -> *)
这表示:给定简单的高级kinded类型,产生最终类型。例如,给定像List 这样的类型构造函数生成最终类型Functor [List]。
从上面的引用中可以看出,至少共同是指* -> *
List
的{{1}}为"更高的类型"。它绝对高于*
。它肯定比你在当前版本的Java中写下的任何东西都要高(如果你用Java编写List
,你可以得到的最好的就是通用类型List需要类型参数blah blah" -error)。