Reputation: 3764
I'm trying to implement either
function, which accepts two generic container and return either of them:
func either<A,B>(a: Container<A>, b: Container<B>) -> ?either Container<A> or Container<B>? {
// choose any of container
return chosen
}
Looks like I need a protocol, that Container must conforms to, so that my either
's return type should be of this protocol.
Is this right solution?
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
}
UPDATE
ok so I've implemented the EitherContainer enum and the final code is following:
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
}
what bothers me now, is Any
type, which shuts the compiler up, but for me looks like a weak crutch. Again same problem rawInput<A, B>(a: A, b: B) -> Any
. rawInput
should return either A or B, but I'm forced to use Any
instead. Should I add another enum for raw options? Any thoughts?
Upvotes: 1
Views: 720
Reputation: 66459
The traditional Either
type looks like this:
enum Either<A, B>
{
case Left(A)
case Right(B)
}
and is more useful, as it's not limited to your Container
type.
(Either
is the "canonical" sum type.)
It would be used like this:
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)
}
}
Upvotes: 3