Scala模式类型与预期类型不兼容

时间:2019-06-29 01:11:37

标签: scala

这是Why can't I run such scala code? (reduceRight List class method)的续集

我正在按照那里接受的答案来重命名我的抽象类并添加列表:List [T]作为方法 foldRight 的参数。

abstract class ListT {
    def foldRight[U](z : U)(list: List[T], op: (T, U) => U): U = list match {
        case Nil => z
        case x :: xs => op(x, foldRight(z)(xs, op))
    }
}

但是我仍然收到'def'行的错误

  

此行未找到多个标记:输入T

1 个答案:

答案 0 :(得分:2)

让我们从头开始,这应该有助于您理解概念。

我们将创建自己的简单功能列表
它将称为MyList,将有一个名为MyNil的空列表,并且cons类/运算符为:!:

// Here we create the type MyList.
// The sealed is used to signal that the only valid implementations
//   will be part of this file. This is because, a List is an ADT.
// The A (which could be a T or whatever) is just a type parameter
//   it means that our list can work with any arbitrary type (like Int, String or My Class)
//   and we just give it a name, in order to be able to refer to it in the code.
// Finally, the plus (+) sign, tells the compiler that MyList is covariant in A.
//    That means: If A <: B Then MyList[A] <: MyList[B]
//    (<: means subtype of)
sealed trait MyList[+A] {
  def head: A // Here we say that the head of a List of As is an A.
  def tail: MyList[A] // As well, a tail of a List of As is another list of As.

  // Here we define the cons operator, to prepend elements to the list.
  // You can see that it will just create a new cons class with the new element as the head & this as the tail.
  // Now, you may be wondering why we added a new type B and why it must be a super type of A
  // You can check out this answer of mine:
  // https://stackoverflow.com/questions/54163830/implementing-a-method-inside-a-scala-parameterized-class-with-a-covariant-type/54164135#54164135
  final def :!:[B >: A](elem: B): MyList[B] =
    new :!:(elem, this)

  // Finally, foldRigh!
  // You can see that we added a new type parameter B.
  // In this case, it does not have any restriction because the way fold works.
  final def foldRight[B](z: B)(op: (A, B) => B): B = this match {
    case MyNil   => z
    case h :!: t =>  op(h, t.foldRight(z)(op))
  }
}

object MyList {
  // Factory.
  def apply[A](elems: A*): MyList[A] =
    if (elems.nonEmpty) {
      elems.head :!: MyList(elems.tail : _*)
    } else {
      MyNil
    }
}

// Implementations of the MyList trait.
final case class :!:[+A](head: A, tail: MyList[A]) extends MyList[A]
final case object MyNil extends MyList[Nothing] {
  override def head = throw new NoSuchElementException("head of empty list")
  override def tail = throw new NoSuchElementException("tail of empty list")
}

现在您可以:

val l1 = MyList(2, 3, 4) // l1: MyList[Int] = 2 :!: 3 :!: 4 :!: MyNil
val l2 = 1 :!: l1 // // l2: MyList[Int] = 1 :!: 2 :!: 3 :!: 4 :!: MyNil
val sum = l2.foldRight(0)(_ + _) // sum: Int = 10