Raf*_*aez 2 functional-programming scala compiler-errors compilation
我有以下功能
def map[A,B](l: List[A])(f: A => B): List[B]
def concat[A](l: List[List[A]]): List[A]
Run Code Online (Sandbox Code Playgroud)
我想实现这个
def flatMap[A,B](l: List[A])(f: A => List[B]): List[B]
Run Code Online (Sandbox Code Playgroud)
现在,我知道正确的解决方案是(所以这不是问题)
def flatMap[A,B](l: List[A])(f: A => List[B]): List[B] =
concat(map(l)(f))
Run Code Online (Sandbox Code Playgroud)
但当我试图解决它时,我首先尝试(我忘了连续)
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)
Run Code Online (Sandbox Code Playgroud)
我无法理解那个错误,因为看起来评价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
Run Code Online (Sandbox Code Playgroud)
任何人都可以解释一下为什么第一次尝试代码的编译被赋予了第二种不同的错误?
您必须知道Scala如何检查类型.它使用的是统一算法.简单来说,它意味着它遵循上/下方法.
回想一下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
类型A => B
.因此编译器抱怨,因为你给f
了类型A => list[B]
.
如果第二个错误的代码,您已经正确计算result
了类型List[List[B]]
.但是,在第二行中,您尝试返回,result
但声明您的函数返回a list[B]
.因此错误消息.