无法将类型 '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 的标准库中的冲突。
在将旧的(不是我的)代码从 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 的标准库中的冲突。