curry function syntax in swift - swift

I was going through this blog. When I tried write curry function on my own method:
func stdCurry(f : (A,B) -> C) -> (A)->(B->C) {
return { (a:A) ->(B -> C) in {
(b:B) -> C in
{
return f(a,b)
}
}
}
}
I got an error:
:7:22: error: declared closure result 'C' is incompatible with contextual type '_'
(b:B) -> C in
^
_
But when I remove the flower parentheses around trailing closure then it won't report any error. Can anybody help me to understand this.

The inner curly braces -> in { ... } tells swift that this inner part is a closure, whereas it in fact only contains a value (the C type evaluation of f(a,b)). If you remove these inner curly braces, your example work.
E.g., try
func stdCurry<A,B,C>(f : (A,B) -> C) -> (A) -> (B -> C) {
return { (a:A) -> (B -> C) in {
(b:B) -> C in
return f(a,b) // <-- this is not a closure (just returns a value of type C`
}
}
}
Note that I've added the generic types to the function signature above (perhaps you function is part of a class and you get your types A, B and C from there).
To make the error above more clear, consider this a bit simpler example (taking a closure and returning it):
/* This is ok */
func myClosure<A,B>(f: (A) -> B) -> (A) -> B {
return {
x in f(x)
}
}
/* Error: return type here is not (A) -> B, but contains
an anonymous closure () -> B */
func myClosure<A,B>(f: (A) -> B) -> (A) -> B {
return {
x in { f (x) }
}
}
/* Ok */
func myClosure<A,B>(f: (A) -> B) -> (A) -> (() -> B) {
return {
x in { f(x) }
}
}
Also note that since Swift knows (infers)---from your function signature---the types in as well as what type/closure to expect in return for each in ... statment, you can omit the closure type ((a:A) -> (B -> C)) as well as the return keyword and make your expression more compact as follows:
func stdCurry<A, B, C>(f: (A, B) -> C) -> A -> (B -> C) {
return { a in { b in f(a, b) } }
}
At your request in the comments below: you can make use of "multiple statements" in the tail e.g. by using the approach of the third "simple example" above, e.g.:
func stdCurry<A,B,C>(f : (A,B) -> C) -> (A) -> (B) -> () -> C {
return { (a:A) -> (B -> () -> C) in {
(b:B) -> () -> C in
return {
// ...
f(a,b)
}
}
}
}
Note that as the function signature grows somewhat "messy", it's favourable to omit these details in the actual closures of your function, i.e.:
func stdCurry<A,B,C>(f : (A,B) -> C) -> (A) -> (B) -> () -> C {
return { a in {
b in
return {
// ...
f(a,b)
}
}
}
}

Related

Swift: generic overloads, definition of "more specialized"

In the below example, why is the foo(f) call ambiguous?
I understand that the second overload could also apply with P == (),
but why isn't the first one considered more specialized,
and therefore a better match?
func foo<R>(_ f: () -> R) { print("r") }
func foo<P, R>(_ f: (P) -> R) { print("pr") }
let f: () -> Int = { 42 }
foo(f) // "Ambiguous use of 'foo'"
I'd say your problem is that you don't explicitely tell the compiler that P == ()
try the following code in a playground :
Void.self == (Void).self // true
Void() == () // true
(Void)() == () // true
(Void) == () // Cannot convert value of type '(Void).Type' to expected argument type '()'
Foo<Int>.self == (() -> Int).self // false
(() -> Int).self == ((Void) -> Int).self // false
Foo<Int>.self == ((Void) -> Int).self // true
Since (Void) cannot be converted to (), I guess the compiler can't understand that foo<R>(_ f: () -> R) is actually a specialization of foo<P, R>(_ f: (P) -> R).
I suggest you create generic type aliases for your function types to help the compiler understand what you're doing eg. :
typealias Bar<P, R> = (P) -> R
typealias Foo<R> = Bar<Void, R>
Now you can can define your function like that :
func foo<R>(_ f: Foo<R>) { print("r") } // Note that this does not trigger a warning.
func foo<P, R>(_ f: Bar<P, R>) { print("pr") }
and then use them with any closure you want :
let f: () -> Int = { 42 }
foo(f) // prints "r"
let b: (Int) -> Int = { $0 }
foo(b) // prints "pr"
let s: (String) -> Double = { _ in 0.0 }
foo(s) // prints "pr"
But you can actually just write :
func foo<R>(_ f: (()) -> R) { print("r") }
func foo<P, R>(_ f: (P) -> R) { print("pr") }
or even :
func foo<R>(_ f: (Void) -> R) { print("r") } // triggers warning :
// When calling this function in Swift 4 or later, you must pass a '()' tuple; did you mean for the input type to be '()'?
func foo<P, R>(_ f: (P) -> R) { print("pr") }
and you get the same results.

functional programming in swift

please, check my snippet, the question is there (my english is too bad to be able to explain my trouble by the words :))
func flip1<A, B, C>(f : ((A, B) -> C), _ b : B, _ a : A) -> C {
return f(a, b)
}
flip1(-, 2, 1) // -1
flip1(/, 2.0, 3.0) // 1.5
// partialy curried version
func flip2<A, B, C>(f : (A, B) -> C, _ i : B, _ j : A) -> C {
return f(j, i)
}
print(flip2(- , 2, 1)) // -1
print(flip2(/,2.0,3.0)) // 1.5
compiles without trouble, but how to use it???
// full curried version
// compiles without trouble, but how to use it???
func flip3<A, B, C>(f : A -> B -> C) -> B -> A -> C {
return { b in { a in f(a)(b) } }
}
/*
* flip3(/)(2.0)(3.0)
*
* error: ambiguous reference to member '/'
* it meands there are more than one candidate for / function
*/
// we need curried version of /, let's define it
func curry<A,B,C>(f: (A, B) -> C) -> A -> B -> C {
return { a in { b in f(a, b) } }
}
/*
* let divideUnknownType = curry(/)
* compiler still complain, as expected :-)
* error: ambiguous use of operator '/'
*/
// and then define the type of it
let divideDoubles: Double->Double->Double = curry(/)
let divideIntegers: Int->Int->Int = curry(/)
// :-)
print(flip3(divideDoubles)(2.0)(3.0)) // 1.5
print(flip3(divideDoubles)(2)(3)) // 1.5
print(flip3(divideIntegers)(2)(3)) // 1
as you can see, it breaks my 'generic' approach. any idea how to solve it?
func flip3<A, B, C>(f: (A, B) -> C) -> B -> A -> C {
return { b in { a in f(a, b) } }
}
flip3(/)(2.0)(3.0) // 1.5

Method with generic type parameter inside Swift extension

While trying to implement a simple lazy list in Swift, I tried creating an extension for enum in Swift, with a generic method inside (emulating a type class-like behavior, as I'm trying out Swift while being a Scala developer most of the time), like so:
enum LazyList<A>{
case Elem(x: A, xs: () -> LazyList<A>)
case Nil()
}
extension LazyList {
func map<B>(f: (A) -> B) -> LazyList<B> {
func lazyMap(l: LazyList<A>, lf: (A) -> B) -> LazyList<B> {
switch l {
case let .Elem(e, es):
return LazyList.Elem(x: lf(e), xs: {() -> LazyList<B> in return lazyMap(es(), lf: lf)})
case .Nil:
return LazyList.Nil()
}
}
return lazyMap(self, lf: f)
}
}
This however does not run in the playground, failing to compile with error below:
error: cannot convert value of type 'LazyList<A>' to expected argument type 'LazyList<_>'
return LazyList.Elem(x: lf(e), xs: {() -> LazyList<B> in return lazyMap(es(), lf: lf)})
How can I get it to compile? Is it because the compiler cannot infer the return type of lazyMap?
simply remove the "LazyList." from your switch cases :)
enum LazyList<A>{
case Elem(x: A, xs: () -> LazyList<A>)
case Nil()
}
extension LazyList {
func map<B>(f: (A) -> B) -> LazyList<B> {
func lazyMap(l: LazyList<A>, lf: (A) -> B) -> LazyList<B> {
switch l {
case let .Elem(e, es):
return .Elem(x: lf(e), xs: {() -> LazyList<B> in return lazyMap(es(), lf: lf)})
case .Nil:
return .Nil()
}
}
return lazyMap(self, lf: f)
}
}

Cannot invoke $function with object of type *

I'm having trouble with a type error that seems to be incorrect. The following code produces the error:
"Cannot invoke baz with argument list of type (f: (A) -> (), g: (String) -> ())" As indicated, the "incorrect" type is the exact type of baz, which is being called.
NB: I pulled out 'succeed' and 'fail' for type clarity, but the same thing happens when using the functions as closures.
class Foo<A> {
..
func baz(f: (A) -> (), g: (String) -> ()) {
.. do some stuff
}
func bar<A, B>(f: (A -> B)) -> Foo<B> {
func succeed(a: A) -> () {
.. do some stuff
}
func fail(s:String) -> () {
.. do some stuff
}
baz(f: succeed, g: fail)
.. do some stuff
}
}
Your generic parameter A declared for function bar overrides the generic type declared for class Foo, you need to remove it:
class Foo<A> {
func baz(f: (A) -> (), g: (String) -> ()) {}
func bar<B>(f: (A -> B)) -> Foo<B> {
func succeed(a: A) -> () {}
func fail(s:String) -> () {}
baz(succeed, g: fail)
return Foo<B>()
}
}
It's something about your A protocol. I changed and created new F so it could compile and it works in my playground:
protocol F {
}
class Foo<A> {
func baz(f: (F) -> (), g: (String) -> ()) {
}
func bar<A, B>(f: (A -> B)) -> Foo<B> {
func succeed(a:F) -> () {}
func fail(s:String) -> () {}
baz(succeed, g:fail)
return Foo<B>()
}
}

How to write a flip method in Swift?

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)?
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.
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)
}
}