This code does not scale, and I thought I can write it using variadic generics...
public protocol Function {
associatedtype Input
associatedtype Output
func call(_ input: Input) -> Output
}
/// Returns `b(a)`, where `a` and `b` are types conforming to `Function`
public func pipe<A, B>(
_ a: A,
_ b: B
) -> ((A.Input) -> B.Output)
where
A: Function,
B: Function,
A.Output == B.Input
{
{ (f: A.Input) -> B.Output in
b.call(
a.call(f)
)
}
}
/// Returns `c(b(a))`, where `a`, `b` and `c` are types conforming to `Function`
public func pipe<A, B, C>(
_ a: A,
_ b: B,
_ c: C
) -> ((A.Input) -> C.Output)
where
A: Function,
B: Function,
C: Function,
A.Output == B.Input, B.Output == C.Input
{
{ (f: A.Input) -> C.Output in
c.call(
b.call(
a.call(f)
)
)
}
}
While I've read most pitches about variadic generics, I have not tried using it it earlier.
So I quite immediately felt lost... I need to express the input of a type is the output of the previous type, but don't think that kind of syntax for type constraints is brought up in SE-0393
public func pipe<First: Function, each M: Function, Last: Function>(
first: First,
middle: repeat each M,
last: Last
) -> ((F.Input) -> L.Output) where repeat (each M).Output == (each M+1).Input // Syntax?!?
{
fatalError("Syntax?! Feels like I wanna use a macro to implement this... LOL.")
}
It feels like... like I wanna create a pack of pair of types...
Never mind how lost I am (quite lost), is my goal achievable with the variadic generics tool shipped in Swift 5.9?
”func reduce” is maybe a better name. The function reduces multiple types conforming to Function into a new single one: (First.Input) -> Last.Output
However, in some hypothetical future, you could use this awful workaround:
public func pipe<First: Function, each AllOtherThanLast: Function, each Item: Function, each AllOtherThanFirst: Function, Last: Function>(_ functions: repeat each Item) -> (First.Input) -> (Last.Output) where (First, repeat each AllOtherThanFirst) == (repeat each Item), (repeat each AllOtherThanLast, Last) == (repeat each Item), (repeat each AllOtherThanLast.Output) == (repeat each AllOtherThanFirst.Input) {
fatalError("Don't get me started on the implementation")
}