swift - 这种类型错误的原因是什么?

标签 swift types

两个问题:

  1. 为什么这段代码编译失败?我相信(但不是 100% 肯定,我可能犯了一个错误)它的类型是正确的。

  2. 错误信息是什么意思?我很困惑为什么预期的参数类型是 _ -> _ (或者也许我只是不知道在这种情况下 _ -> _ 是什么意思)。这道题的目的是学习如何正确诊断这个错误信息,如果我以后再遇到它。

代码:

此代码无法编译并显示错误消息“无法将类型 '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))
    }
}

enter image description here

附加信息:

起初,我认为问题出在类型推断上,所以我尝试显式写出类型,但也失败了:

enter image description here

enter image description here

然而,这编译得很好(与我原来的 map 版本的唯一区别是 <B> 传递给 ZipList 初始化程序):

func map4<B>(f: A -> B) -> ZipList<B> {
    return ZipList<B>(xs: self.xs.map(f))
}

最佳答案

问题是当您没有显式提供 ZipList 的通用参数类型时当您引用它时,编译器会尝试为您推断它——它并不总是是正确的。

因为您已经在 ZipList<A> 中了类,编译器将尝试推断 ZipList成为ZipList<A>当您省略通用参数时(有关此行为的更多信息,请参阅 this question)。

因此它现在期望输入 [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() 
    }
}

事实上,编译器完全忽略了map() 返回值的显式类型注释。方法是一个错误,由 SR-1789 跟踪.正如 Jordan Rose 在报告的评论中所描述的那样,原因是:

It seems to be a case of us eagerly assuming the parameters are the same as for self. (That's usually a feature, but not when it gets in the way of other inference.)

正如您已经找到的那样,解决方案是显式声明 ZipList 的通用参数类型当您创建一个新实例时:

return ZipList<B>(xs: xs.map(f))

这强制通用参数的类型为 B ,因此防止 Swift 错误地推断它,允许 map功能来解决。

至于错误消息“无法将类型 'A -> B' 的值转换为预期参数类型 '_ -> _”的含义,_在这种情况下,它只是指编译器无法解析的泛型类型(我知道这不是有用的错误消息)。因此,所有编译器都在告诉您,它期待一个接受未知类型输入并返回相同类型的函数。

在诊断此类错误消息时,将表达式拆分为多个子表达式并检查每个子表达式的类型以尝试找到不匹配项通常会有所帮助。它还有助于开始简化示例(例如在您的 init() 方法中使用 init(xs:[A]) 而不是 map),直到您遇到更有帮助的错误消息。

关于swift - 这种类型错误的原因是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37862276/

相关文章:

ios - 如何使对象(SKSprite 节点)在单击时消失

Swift - 仅从字符串中获取字母数字字符

C++:实现一个接收 lambda 作为输入的高阶函数

scala - 映射到相同类型的 Traversable 的 Traversable 类型

ios - Swift:返回 self 类型的数组

java - BIT(1) HIbernate JPA 映射

python - np.array arr.itemsize 与 sys.getsizeof(arr[0])

ios - 索引(其中 :) method in swift is producing the wrong index

macos - 如何在 OSX 中使用 Swift 发送 api key 进行身份验证?

ios - 在 UITextView 中快速将 'Return' 按钮功能更改为 'Done'