无法将类型 'Result<Data, Error>' 的值转换为闭包结果类型 'Result<T, E>'

Cannot convert value of type 'Result<Data, Error>' to closure result type 'Result<T, E>'

在将旧的(不是我的)代码从 swift 2 转换为 swift 4

后,我需要有关泛型和 return 类型的帮助
let cryptedJsonData = packet.encodeJSON()
                .flatMap { [=14=].gzippedData() } //here I am getting error

Cannot convert value of type 'Result<Data, Error>' to closure result type 'Result<T, E>'

平面图函数

extension Result {

func map<U>( _ function: @escaping (T) -> U ) -> Result<U, E> {
    return flatMap { .success( function( [=15=] ) ) }
}

func flatMap<U>( _ function: (T) -> Result<U, E> ) -> Result<U, E> {

    switch self {
        case .success(let value): return function(value)
        case .failure(let error): return .failure(error)
    }
}

}

gzippedData()

 private let CHUNK_SIZE: Int = 2 ^ 14

 func gzippedData() -> Result<Data, Error> {

    var data = Data(count: CHUNK_SIZE)

    return .success( data as Data)
}

结果

enum Result<T, E> {

    case success(T)
    case failure(E)
}

如果您定义了自己的 Result 类型,我怀疑问题源于不同模块中 Result 的两个定义之间的类型不兼容。

请注意,Swift 的标准库中已经定义了一个 Result 类型(参见 https://developer.apple.com/documentation/swift/result),其实现与您发布的非常接近。如果您确实定义了自己的类型,则 encodeJSON() 返回的 Result 可能与 gzippedData() 返回的 Result 不同。不幸的是,Swift 处理名称冲突的能力非常差,尤其是当名称与标准库中的名称发生冲突时。

这里有一个方法可以重现您的问题:

// This enum is defined in my own source.
enum Result<T, E> {
  case success(T)
  case failure(E)
}

// This is an dummy error type, with the sole purpose of specializing `Result`.
enum SomeError: Error {}

// This extension has for sole purpose to add a method to `String` that returns
// an instance of *my* `Result` type.
extension String {
  func foo() -> Result<String, SomeError> {
    return .success(self)
  }
}

// Now assume this function comes from a third party library that uses Swift's
// `Result` type, from the standard library.
func bar() -> Swift.Result<String, SomeError> {
  return .success("Hello, World!")
}

// The following line will trigger the exact same error as yours, because the
// `Result` type that expects `flatMap`'s argument is not *my* `Result` type,
// but that of Swift's standard library.
bar().flatMap { [=10=].foo() }

请注意,如果您将 Swift.Result 替换为 bar 的共同域上的 Result(假设您还提供了 flatMap 的定义,则此示例将编译得很好).


如果您定义了自己的 Result 类型,我建议您要么使用 Swift 的类型,我猜它的行为完全符合您的预期,要么重命名您自己的类型,这样它的定义就不再存在与 Swift 的标准库中的冲突。