了解类型参数



从scala中的功能编程中查看IO Monad的签名的一部分:

trait IO[+A] { self =>
  def run: A
  def map[B](f: A => B): IO[B] =
    new IO[B] { def run = f(self.run) }

我了解,IO[+A]表示IO类型采用" A或其子类"的类型参数。

查看def map[B]...B是此功能涉及的一种类型。使用map[B](f: A => B): IO[B]很有用,因为据我了解,您可以将B列为f的返回类型,以及IO的返回类型参数?

因此,以下实现将导致编译时间问题:

map(f: Int => String): IO[Int]

我不确定您在这种情况下通过"实现"的意思: map(f: Int => String): IO[Int]。如果您是指调用map传递函数Int => String,则返回IO[String]- callee不会在返回哪种类型的情况下获得发言权。

如果您是指使用override def map(f: Int => String): IO[String]map的实现(您不应该这样做),那么不是 覆盖任何东西,因为在覆盖时无法删除类型参数,并且您也不能更改它收到的参数的类型,并且可以将返回类型更改为子类型,但是IO[String]不是IO[B]的子类型,因此也不同。

,因此+AT <: A相似。这意味着"适用于包括a的所有子类型"。此"限制"在这里很有用,因为您应该将f函数传递给map方法,并且将其限制在特定类型的A及其子类型中。因此,当您扩展班级中的特质时,您可以在typesafe时替换f

B这是将f应用于A的结果。由于它是一个单子,您不仅可以返回B,还可以返回IO[B]。换句话说,它可能失败,您可能会被B包裹在"成功"或某种"失败"中。

请注意,self的类型是+A,而新创建的IO[B]实际上没有计算任何内容,它只是围绕run的结果,该结果必须是B。由于您期望在IO中发生失败,并且由于它是一个单子,因此您可以将f(self.run)的应用程序包裹起来,从而创建Monad IO[B](如map方法签名所承诺)。

最后,正如您所说的map(f: Int => String): IO[Int]不应编译的,因为Int不是String的子类型。

最新更新