【问题标题】:Function that return either of two generics返回两个泛型之一的函数
【发布时间】:2015-09-19 12:44:28
【问题描述】:

我正在尝试实现either 函数,它接受两个通用容器并返回其中一个:

func either<A,B>(a: Container<A>, b: Container<B>) -> ?either Container<A> or Container<B>? {
    // choose any of container
    return chosen
}

看起来我需要一个协议,容器必须遵守,所以我的either 的返回类型应该是这个协议。 这是正确的解决方案吗?

protocol ContainerProtocol
struct Container<T>: ContainerProtocol

func either<A: ContainerProtocol, B:ContainerProtocol, C:ContainerProtocol>(a: A, b: B) -> C {
    // choose any of container
    return chosen
}

更新

好的,我已经实现了 EitherContainer 枚举,最终代码如下:

struct Container<T>: Unique {
    typealias UnderlyingObject = T
    var object: UnderlyingObject
    var uniqueId: String
}

enum EitherContainer<A,B> {
    case a(container: Container<A>)
    case b(container: Container<B>)
}

func wrappedInput<A,B>(wra: Container<A>, wrb: Container<B>, paramClosure: (Container<A>, Container<B>) -> EitherContainer<A,B>) -> EitherContainer<A,B> {
    //do some work here
    return paramClosure(wra, wrb)
}

func rawInput<A, B>(a: A, b: B) -> Any {
    let wrappedA = Container(object: a, uniqueId: "a")
    let wrappedB = Container(object: b, uniqueId: "b")
    let wrappedRes = wrappedInput(wrappedA, wrb: wrappedB) {
        (a1: Container, a2: Container) -> EitherContainer<A,B> in
        // do some work here
        return EitherContainer.a(container: a1)
    }
    var rawRes: Any
    switch wrappedRes {
    case .a(let container):
        rawRes = container.object
    case .b(let container):
        rawRes = container.object
    }
    return rawRes
}

现在困扰我的是Any 类型,它会关闭编译器,但对我来说看起来像是一个弱拐杖。同样的问题rawInput&lt;A, B&gt;(a: A, b: B) -&gt; AnyrawInput 应该返回 A 或 B,但我不得不改用 Any。我应该为原始选项添加另一个枚举吗?有什么想法吗?

【问题讨论】:

  • 您的解决方案绝对有效。另一种方法是实现enum Either&lt;A, B&gt; 类型,其中两种情况对应于每种可能性。然后您可以在返回值上switch 并获取选择的容器。这样你的类型信息就不会通过函数丢失。
  • @Peter 是的,枚举解决方案非常简洁

标签: swift generics swift2


【解决方案1】:

传统的Either 类型如下所示:

enum Either<A, B>
{
    case Left(A)
    case Right(B)
}

而且更有用,因为它不限于您的 Container 类型。
Either 是“规范”求和类型。)

它会这样使用:

func wrappedInput<A, B> (
    a : Container<A>,
    b: Container<B>,
    paramClosure: (Container<A>, Container<B>) -> Either<Container<A>,Container<B>>
    ) -> Either<Container<A>, Container<B>>
{
    return Either.Left(a) // Dummy
}

func rawInput<A, B>(a: A, b: B) -> Either<A,B> {
    let wrappedA = Container(object: a, uniqueId: "a")
    let wrappedB = Container(object: b, uniqueId: "b")
    let wrappedRes = wrappedInput(wrappedA, b: wrappedB) {
        (a1: Container, a2: Container) -> Either<Container<A>, Container<B>> in
        // do some work here
        return Either.Left(a1)
    }

    switch wrappedRes {
    case .Left(let container):
        return Either.Left(container.object)
    case .Right(let container):
        return Either.Right(container.object)
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 2022-08-11
    • 1970-01-01
    相关资源
    最近更新 更多