为什么有可能通过不高的kinded类型?

时间:2018-02-07 08:44:24

标签: scala scala-cats

我正在阅读这本书https://underscore.io/books/scala-with-cats/并尝试了解猫的逆变 在页面68上有一个在Cats

中实现 Contravariant的示例
  

我们可以使用Contravariant方法召唤Contravariant.apply的实例。 Cats为使用的数据类型提供实例   参数,包括EqShowFunction1。这是一个例子:

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不是更高级的类型。

1 个答案:

答案 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)

其中Contravariantcompanion object of trait Contravariantinst是隐式提供的 type Contravariant[Show]的实例。同样,一切都无缝地融合在一起。

备注命名法。我会说Show是更高级别的"。它绝不是决定性的,但我喜欢Atlassian Blog [强调和代码缩进矿]中的以下引用:

  

此外,您可以使用更高级别的类型进行参数化的种类。所以,某些东西不仅可以采用一种类型,而且可以采用本身需要类型参数的东西。一个例子是协变仿函数:Functor [F [_]],它有种类:

((* -> *) -> *)
  

这表示:给定简单的高级kinded类型,产生最终类型。例如,给定像List 这样的类型构造函数生成最终类型Functor [List]。

从上面的引用中可以看出,至少共同是指* -> * List的{​​{1}}为"更高的类型"。它绝对高于*。它肯定比你在当前版本的Java中写下的任何东西都要高(如果你用Java编写List,你可以得到的最好的就是通用类型List需要类型参数blah blah" -error)。