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

时间:2019-07-18 07:51:12

标签: swift swift4

在将旧的(不是我的)代码从swift 2转换为swift 4之后,我需要泛型和返回类型的帮助

let cryptedJsonData = packet.encodeJSON()
                .flatMap { $0.gzippedData() } //here I am getting error

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

flatmap函数

extension Result {

func map<U>( _ function: @escaping (T) -> U ) -> Result<U, E> {
    return flatMap { .success( function( $0 ) ) }
}

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)
}

1 个答案:

答案 0 :(得分:1)

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

请注意,Swift的标准库中已经定义了一种Result类型(请参见https://developer.apple.com/documentation/swift/result),其实现与您发布的内容非常接近。如果您实际定义了自己的类型,则Result返回的encodeJSON()Result返回的gzippedData()可能会有所不同。不幸的是,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 { $0.foo() }

请注意,如果您在Swift.Result的共域上简单地用Result替换bar,则此示例可以很好地编译(假设您还提供了flatMap的定义)。


如果您定义了自己的Result类型,建议您使用Swift的类型(我猜它的行为与您的预期完全相同),或者重命名您自己的类型,以使其定义不再与Swift的标准库中的定义冲突。