Avatar
omochimetaru 1/24/2020 7:04 AM
// ============================================================================= // With the following hack, the result type of the second `curry` function might // become expressible. // ============================================================================= enum CurryHelper<variadic T, Result> { #ifempty T typealias Fn = Result #else typealias Fn = (#head(T)) -> CurryHelper<#tail(T), Result: Result>.Fn #endif } // CurryHelper<A, B, C, R>.Fn // CurryHelper<A, B, C, R>.Fn = (A) -> CurryHelper<B, C, Result: R>.Fn // -> (B) -> CurryHelper<C, Result: R>.Fn // -> (C) -> CurryHelper<Result: R>.Fn // -> R // CurryHelper<A, B, C, R>.Fn = (A) -> (B) -> (C) -> R func curry<A, B, C, variadic D, Result>( _ fn: @escaping (A, B, C, D...) -> Result ) -> CurryHelper<A, B, C, D..., Result>.Fn { return { a in curry { otherValues in fn(a, otherValues...) } } }