了解类型参数

时间:2014-02-06 03:32:59

标签: scala

查看来自Functional Programming in ScalaIO 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]

2 个答案:

答案 0 :(得分:3)

我不确定在这种情况下“实施”是什么意思:map(f: Int => String): IO[Int]。如果你的意思是调用map传递函数Int => String,那么返回IO[String] - 被调用者不会对返回的类型有所说明。

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

答案 1 :(得分:1)

因此+AT <: A的含义相似。这意味着“对于A的所有亚型,包括A”。这个“限制”在这里很有用,因为您应该将f函数传递给map方法,并且您将其限制为特定类型A并且它是子类型。因此,当您在类中扩展特征时,您可以在类型安全时替换f

B这是将f应用于A的结果。由于它是Monad,因此您不仅可以获得B,还可以获得IO[B]。换句话说,它可能会失败,你可能会被B包裹在“成功”或某种“失败”中。

请注意,self的类型为+A,而新创建的IO[B]实际上并未计算任何内容,它只包含run的结果是B。由于您希望在IO中发生故障,并且因为它是Monad,因此您可以使用f(self.run)创建monad IO[B](由map方法签名承诺)的应用程序结果。

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