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

原文 标签 swift types

两个问题:

  • 为什么这段代码无法编译?我相信(但不是 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))
        }
    }
    

    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功能来解决。

    至于错误信息“Cannot convert value of type 'A -> B' to expected argument type '_ -> _”是什么意思,_在这种情况下,仅指编译器无法解析的泛型类型(我知道这不是有用的错误消息)。所以编译器告诉你的只是它期待一个接受未知类型输入并返回相同类型的函数。

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

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

    相关文章:

    c# - 始终使用自定义数据类型

    generics - Haskell 中的泛型类型转换

    使用泛型时的 C# 构造函数问题

    ios - 如何在此 View Controller 中显示inputAccessoryView

    ios - 如何在TabBarController中的TabBar下方添加imageView

    objective-c - 如何在NSCollectionView内绘制bezierPath?

    json - Swift RestKit不会在体内发布JSON

    c - 在 C 中存储微秒总和的正确数据类型是什么

    c - 了解声明C字符串的两种方法

    swift - 在Swift中创建自定义CodingKey对象