Reputation: 23
I want to write a flip method in Swift.
Here is the signature.
Prelude> :t flip
flip :: (a -> b -> c) -> b -> a -> c
My code in Swift:
func flip1<A, B, C>(f: A->B->C) -> (B->A->C) {
return { (valueB: B, valueA: A) in
return f(valueA, valueB)
}
}
func flip2<A, B, C>(f: A->B->C) -> (B->A->C) {
return { (valueB: B) in
return { (valueA: A) in
return f(valueA)(valueB)
}
}
}
The flip1
method can not compile. There is an error Extra argument in call
at line return f(valueA, valueB)
The flip2
method works fine, except the flipped method can only be called like this method(1)(2)
.
How to write the flip
method so that I can use the flipped method like method(1, 2)
and method(1)(2)
?
Upvotes: 3
Views: 275
Reputation: 9925
This is the @MartinR answer updated to Swift 5.1
func flip<A, B, C>(_ f: @escaping (A, B)->C) -> (B, A)->C {
return { (valueB: B, valueA: A) in
return f(valueA, valueB)
}
}
let x = flip(-)(10, 5) println(x) // -5
It can slightly be shortened to
func flip<A, B, C>(_ f: @escaping (A, B)->C) -> (B, A)->C {
{ (valueB: B, valueA: A) in
f(valueA, valueB)
}
}
Upvotes: 0
Reputation: 539805
A->B->C
is the type of a function taking one argument of type A
and returning a function B->C
(a "curried" function). The type of a function taking
two arguments is (A, B)->C
:
func flip<A, B, C>(f: (A, B)->C) -> (B, A)->C {
return { (valueB: B, valueA: A) in
return f(valueA, valueB)
}
}
let x = flip(-)(10, 5)
println(x) // -5
It can slightly be shortened to
func flip<A, B, C>(f: (A, B)->C) -> (B, A)->C {
return { (valueB, valueA) in
f(valueA, valueB)
}
}
due to automatic type inference.
As far as I know, Swift does not automatically convert functions taking multiple arguments into curried functions, compare Typecase regular Swift function to Curry Function.
Upvotes: 2