我有以下功能
def map[A,B](l: List[A])(f: A => B): List[B]
def concat[A](l: List[List[A]]): List[A]
我想实现这个
def flatMap[A,B](l: List[A])(f: A => List[B]): List[B]
现在,我知道正确的解决方案是(所以这不是问题)
def flatMap[A,B](l: List[A])(f: A => List[B]): List[B] =
concat(map(l)(f))
但是当我试图解决它时,我首先尝试(我忘了连续)
def flatMap[A,B](l: List[A])(f: A => List[B]): List[B] =
map(l)(f)
// compilation output
[error] found : A => fpinscala.datastructures.List[B]
[error] required: A => B
[error] map(l)(f)
我无法理解那个错误,因为看起来像map(l)(f)
的评价是错误的,但事实并非如此,它是flatMap函数的返回值有什么不对。
事实上,如果在两行代码中分解相同的实现,我们可以看到Scala编译器抱怨另一个不同的错误 - 实际上是我在前面的代码中也预期的错误。
def flatMap[A,B](l: List[A])(f: A => List[B]): List[B] = {
var result = map(l)(f)
result
}
// compilation output
[error] found : fpinscala.datastructures.List[fpinscala.datastructures.List[B]]
[error] required: fpinscala.datastructures.List[B]
[error] result
有人能解释一下为什么第一次尝试代码的编译被赋予了第二种不同的错误吗?
答案 0 :(得分:5)
您必须知道Scala如何检查类型。它正在使用Unification algorithm。简单来说,它意味着它遵循上/下方法。
回想一下,map
的类型为List[U] => (U => V) => List[V]
(类型U
和V
都是)。在第一个错误的代码中,您写道您的函数返回List[B]
。因此,您告诉Scala map(l)(f)
必须是List[B]
类型。现在你以上/下的方式传播constains。要使map(l)(f)
属于List[B]
类型,您需要l
类型List[A]
(A
为{}}和f
类型{ {1}}。因此,编译器抱怨,因为您提供了类型为A => B
的{{1}}。
如果第二个错误的代码,您已经正确计算了f
类型的A => list[B]
。但是,在第二行中,您尝试返回result
,但声明您的函数返回List[List[B]]
。因此错误消息。