【问题标题】:Scala type inference confusionScala 类型推断混淆
【发布时间】:2018-08-22 19:26:08
【问题描述】:
  trait IO[F[_], +A]
  case class Pure[F[_], +A](get: A) extends IO[F,A]
  case class Request[F[_], I, +A](expr: F[I], receive: I => IO[F,A]) extends IO[F,A]

  trait Console[A]
  case object ReadLine extends Console[Option[String]]
  case class PrintLine(s: String) extends Console[Unit]

  trait Run[F[_]] {
    def apply[A](expr: F[A]): (A, Run[F])
  }

  object IO {
    @annotation.tailrec
    def run[F[_],A](R: Run[F])(io: IO[F,A]): A = io match {
      case Pure(a) => a
      case Request(expr,recv) =>
        R(expr) match { case (e,r2) => println(e.getClass); run(r2)(recv(e)) }
    }
  }

代码来自“Scala 中的函数式编程”,IDE 抱怨模式匹配中的“recv”应该只接收 Nothing 类型作为其参数,但实际上类型是 Any。但是,它仍然通过了编译。我还认为 recv 将被推断为 Run[F[?], A] 函数的 Request[F[?], Nothing, A] 。这里发生了什么?看起来 Scala 有一些动态特性。它可以推断出运行时中的 I 类型是不正确的。

【问题讨论】:

标签: scala


【解决方案1】:

根据Request的定义,我们知道expr的类型为F[I]recv的类型为I => IO[F, A]。根据Run 的定义,我们知道R(expr) 的类型为(I, Run[F])。所以eI 类型,recv 是一个接受I 类型参数的函数。

这告诉我们recv(e) 的类型很好,尽管我们对I 一无所知。

我也认为 recv 将被推断为 Run[F[?], A] 函数的 Request[F[?], Nothing, A]。

不,recv 的类型为 I => IO[F, A],其中 FArun 定义中的类型变量,I 是用作 Request 的第二个类型参数的类型Request 对象的创建时间。

【讨论】:

猜你喜欢
  • 2019-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-29
  • 2016-09-11
  • 1970-01-01
  • 2016-12-27
  • 2012-02-07
相关资源
最近更新 更多