Scala中zipAll实现中的奇怪类型不匹配

时间:2014-08-30 18:56:47

标签: scala types intellij-idea mismatch any

我正在使用Scala [MEAP]中的函数编程一书在Scala中做一些练习。在Strictness和laziness一章中,我必须为Stream实现一个zipAll实现。相关代码:

case object Empty extends Stream[Nothing]
case class Cons[+A](h: () => A, t: () => Stream[A]) extends Stream[A]

def cons[A](hd: => A, tl: => Stream[A]): Stream[A] = {
  lazy val head = hd
  lazy val tail = tl
  Cons(() => head, () => tail)
}

def empty[A]: Stream[A] = Empty 

def unfold[A, S](z: S)(f: S => Option[(A, S)]): Stream[A] = f(z) match {
  case Some((a, s)) => cons(a, unfold(s)(f))
  case None => empty
} 

问题是我得到一个奇怪的类型不匹配。 zipAll函数应该继续遍历,只要任一流有更多元素并且它使用Option来指示每个流是否已经用尽。 zipAll函数必须通过展开实现(上图)。我得到了本书作者的正确答案,它没有实现简单的zipAll,而是使用zipWithAll来抽象它。但是,我的解决方案并不是抽象的,我想知道它为什么不起作用。

我的回答:

def myZipAll[B, C](s2: Stream[B]): Stream[(Option[A], Option[B])] =
  unfold((this, s2)){
    case (Empty, Empty) => None
    case (Cons(h, t), Empty) => Some( ((Some(h()), Option.empty[B]), (t(), empty[B])) )
    case (Empty, Cons(h, t)) => Some( ((Option.empty[A], Some(h())), (empty[A], t())) )
    case (Cons(h1, t1), Cons(h2, t2)) => Some( ( (Some(h1()), Some(h2())), (t1(), t2())) )
  }

作者的解决方案(可行):

def zipWithAll[B, C](s2: Stream[B])(f: (Option[A], Option[B]) => C): Stream[C] =
  unfold((this, s2)){
    case (Empty, Empty) => None
    case (Cons(h, t), Empty) => Some( (f(Some(h()), Option.empty[B]), (t(), empty[B])) )
    case (Empty, Cons(h, t)) => Some( (f(Option.empty[A], Some(h())), (empty[A], t())) )
    case (Cons(h1, t1), Cons(h2, t2)) => Some( ( f(Some(h1()), Some(h2())), (t1(), t2())) )
}

def zipAll[B](s2: Stream[B]): Stream[(Option[A], Option[B])] =
  zipWithAll(s2)((_, _))

来自Intellij的错误消息说:" Stream [(Any,Any)]"类型的表达式不符合预期类型Stream [(选项[A],选项[B])]。

1 个答案:

答案 0 :(得分:0)

您的解决方案可以从命令行为我工作,因此它可能是一个IntelliJ错误。当您看到此类型的错误时,编译器完成的类型推断因任何原因而失败,因此您将获得“Any”。我的解决方案与您的解决方案一样,但我使用了Option,其中使用了Option.empty [A]和Option.empty [B]。试试吧。