两个问题:
为什么这段代码无法编译?我相信(但我不是100%肯定,我可能犯了一个错误)它是类型正确的.
错误消息是什么意思?我很困惑为什么预期的参数类型是_ -> _(或者我可能只是不知道它_ -> _在这种情况下意味着什么).这个问题的目标是学习如何正确诊断此错误消息,如果我将来再次遇到它.
代码:
此代码无法编译,并显示错误消息"无法将类型'A - > B'的值转换为预期的参数类型'_ - > _':
class ZipList<A> {
let xs: [A]
init(xs: [A]) {
self.xs = xs
}
func map<B>(f: A -> B) -> ZipList<B> {
return ZipList(xs: self.xs.map(f))
}
}
Run Code Online (Sandbox Code Playgroud)
附加信息:
起初,我认为问题是类型推断,所以我尝试明确写出类型,但也失败了:
但是,这个编译得很好(与原始map版本的唯一区别是<B>传递给ZipList初始化器):
func map4<B>(f: A -> B) -> ZipList<B> {
return ZipList<B>(xs: self.xs.map(f))
}
Run Code Online (Sandbox Code Playgroud)
问题是,当您ZipList在引用它时没有显式提供泛型参数类型时,编译器将尝试为您推断它 - 它并不总是正确的.
正如你已经是一个内部ZipList<A>类,编译器会尝试推断ZipList是ZipList<A>,当你忽略泛型参数(见这个问题,有关此问题的更多信息).
因此,它现在预计的输入[A]在ZipList(xs:_)初始化器,这意味着地图功能被推断为A -> A,这你要传递A -> B给,导致类型不匹配(这是为什么f被高亮显示在你的错误的问题).
如果您简化示例只是init()在ZipList不提供参数的情况下调用您的示例,您将看到更有用的错误消息:
class ZipList<A> {
init() {}
func map<B>() -> ZipList<B> {
// error: Cannot convert return expression of type 'ZipList<A>' to 'ZipList<B>'
return ZipList()
}
}
Run Code Online (Sandbox Code Playgroud)
编译器完全忽略map()方法返回的显式类型注释这一事实是一个错误,并由SR-1789跟踪.乔丹·罗斯在报告评论中描述的原因是:
似乎是我们急切地假设参数与之相同的情况
self.(这通常是一个功能,但不会妨碍其他推断.)
正如您已经发现的那样,解决方案是ZipList在创建新实例时显式声明泛型参数类型:
return ZipList<B>(xs: xs.map(f))
Run Code Online (Sandbox Code Playgroud)
这会强制泛型参数为类型B,因此阻止Swift错误地推断它,允许map函数解析.
至于什么错误消息" 无法将类型'A - > B'的值转换为期望的参数类型'_ - > _ "意味着,_在这种情况下只是指编译器无法解析的泛型类型(不是有用的错误消息) , 我知道).所以编译器告诉你的是,它期望一个函数接受一个未知类型的输入,并返回相同的类型.
在诊断这些类型的错误消息时,通常有助于将表达式拆分为多个子表达式,并检查每个类型的类型以尝试查找不匹配.它还可以帮助您开始简化示例(比如使用init()而不是init(xs:[A])在您的map方法中),直到您遇到更有用的错误消息.
| 归档时间: |
|
| 查看次数: |
204 次 |
| 最近记录: |