The short version:
Is it possible to limit an extension to a type where some associatedtype
is not a specific type. For example:
protocol Foo {
associatedtype SomeAssociatedType
}
extension Foo where Self.SomeAssociatedType != Void {
// . . .
}
The longer version:
I have a number of types I'm defining that describes steps in a series of operations. Each operation has a single input type, and a single output, described by a pair of associated types.
protocol Operation {
associatedtype Input
associatedtype Output
func perform(with input: Input) -> Output
}
I have some code that allows a chain of operations to be created where one Operation
output matches another Operation
input. For example with this silly example:
struct ConvertIntToDoubleOperation: Operation {
typealias Input = Int
typealias Output = Double
func perform(with input: Int) -> Double {
Double(input)
}
}
extension Operation where Self.Output == Int {
var toDouble: AnyOperation<Self.Input, Double> {
self.then(ConvertIntToDoubleOperation())
}
}
// let double = someIntegerOperation.toDouble
In some cases though, an operation may define the end of the chain of operations, by specifying that its output type is Void. Another silly example:
struct PrintOperation<T>: Operation {
typealias Input = T
typealias Output = Void
func perform(with input: T) -> Void {
print(input)
}
}
In this case, nothing can be chained after this.
However, now I want to add a function for adding this operation to the chain. And I want to add a function that will be added to all transactions who have an associated type that is not Void()
.
In other words... I want to allow this:
someIntegerOperation.toDouble.print
// or...
someIntegerOperation.print
But not:
someIntegerOperation.toDouble.print.print
// or...
someIntegerOperation.print.print
As the output of print
is a Void
, so it doesn't make sense to chain another operation after it.
Ideally I could do something like this:
extension Operation where Self.Output != Void {
var print: AnyOperation<Self.Input, Void> {
self.then(PrintOperation())
}
}
But I cannot work out what the syntax should be here. It's easy to define the extension where something is true, but how do we handle cases where something is false? Is this even possible?