【问题标题】:Why does the Scala compiler recognize a generic type twice为什么 Scala 编译器会两次识别泛型类型
【发布时间】:2020-06-30 02:12:20
【问题描述】:

Scala 新手在这里遇到一个令人困惑的编译器错误。我不清楚为什么编译器将msort[T] 中的通用参数类型T 识别为与(lt: (T, T) => Boolean) 中的参数类型T 不同的类型。

def msort[T](xs: List[T])(lt: (T, T) => Boolean): List[T] = {
    val n = xs.length/2
    if (n == 0) xs
    else {
        def merge[T](xs: List[T], ys: List[T]): List[T] = 
            (xs, ys) match {
                case (Nil, _) => ys
                case (_, Nil) => xs
                case (x :: xs1, y :: ys1) => 
                    if (lt(x, y))
                        x :: merge(xs1, ys)
                    else
                        y :: merge(xs, ys1)
            }
        val (fst, snd) = xs splitAt n
        merge(msort(fst)(lt), msort(snd)(lt))
    }
}

The issue is with line 10 测试 x 和 y 的顺序时if (lt(x, y))。我收到 2 个类型不匹配错误,但不确定出了什么问题。

[error] -- [E007] Type Mismatch Error: /..../src/main/scala/Main.scala:10:27 
[error] 10 |                    if (lt(x, y))
[error]    |                           ^
[error]    |                           Found:    (x : T)
[error]    |                           Required: T²
[error]    |
[error]    |                           where:    T  is a type in method merge
[error]    |                                     T² is a type in method msort
[error] -- [E007] Type Mismatch Error: /..../src/main/scala/Main.scala:10:30 
[error] 10 |                    if (lt(x, y))
[error]    |                              ^
[error]    |                              Found:    (y : T)
[error]    |                              Required: T²
[error]    |
[error]    |                              where:    T  is a type in method merge
[error]    |                                        T² is a type in method msort
[error] two errors found

开发环境

Mac OsX
sbt.version=1.3.2
scalaVersion=2.13.1

【问题讨论】:

  • 顺便说一句,我认为用scala.math.Ordering[T](提供lt的类型类)替换(T, T) => Boolean会有一些好处
  • 伟大的点@cchantep。使用 implicit ord: Ordering 有助于利用 Scala 的类型推断进行一些良好的封装

标签: scala generics polymorphism


【解决方案1】:

内部方法merge的类型参数T正在遮蔽外部方法msort的同名类型参数T。而是尝试像这样从merge 中删除类型参数

def msort[T](xs: List[T])(lt: (T, T) => Boolean): List[T] = {
  val n = xs.length/2
  if (n == 0) xs
  else {
    def merge(xs: List[T], ys: List[T]): List[T] =
      (xs, ys) match {
        case (Nil, _) => ys
        case (_, Nil) => xs
        case (x :: xs1, y :: ys1) =>
          if (lt(x, y))
            x :: merge(xs1, ys)
          else
            y :: merge(xs, ys1)
      }
    val (fst, snd) = xs splitAt n
    merge(msort(fst)(lt), msort(snd)(lt))
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多