Passing function on self without parameters to the function (like map/filter etc.) doesn't call the function but wraps as a block without args - swift

Given:
class Elem {
func f() -> AnotherElem {
return AnotherElem(elem: self)
}
}
I want to call the map function on array of Elems passing the function f:
Sample code:
collection.map { $0.f() }
However, I don't like this {} notation so I was thinking whether or not I can pass a function as an argument (which in my eyes increases readability), and indeed I can
What I want is to do the following:
collection.map(Elem.f)
The last is valid syntax however the type of the array is the following: [() -> AnotherElem] instead of expected [AnotherElem] type.
Is a bug or a feature?
Obviously, this could be solved by calling map again and calling the array of blocks, but this is not the problem I'm having.
I'm struggling to understand why it is the way it is

This is expected behaviour, i.e. not a bug.
If you try to use an instance method someMethod of the form(T) -> U directly like this:
SomeType.someMethod
The type of that expression is (SomeType) -> (T) -> U. In your case, The type of Elem.f is (Elem) -> () -> AnotherElem.
Why is it designed like this? It is so that you can pass an instance to SomeType.someMethod, and then get the original instance method:
let f = SomeType.someMethod(instanceOfSomeType)
I guess this could be somewhat called "currying".
Anyway, you would need another function to transform Elem.f:
func uncurry<T, U>(_ f: #escaping (T) -> () -> U) -> (T) -> U {
return { f($0)() }
}
Now passing uncurry(Elem.f) will work.

Related

Reduce array of closures into single closure

Suppose I have an array of closures which can all be composed with one another (i.e., endomorphisms, their input and output types are the same). How can I compose these closures into a single closure?
For reference, I was trying to design something like the following.
struct MyType {
typealias MyClosure: (T) -> T
private var myClosures: [MyClosure] = [ ... ]
public var closure: MyClosure {
get {
return ? // somehow compose all of myClosures into a single closure here
}
}
}
My first thought was to use reduce, à la myClosures.reduce(STARTING) { a, b in b(a) },
but this requires a starting value to be supplied, and then successively applies the closures to it. I don't want to apply the closures to anything (yet), but just synthesize the private list of closures into a single, public closure which can be applied later. Given the way reduce is
defined, I expect this would look something like
myClosures.reduce(identity) { a, b in compose(a, b) }
func identity(_ input: T) { return input }
func compose(a: MyClosure, b: MyClosure) -> MyClosure { return b(a) }
but the type of b(a) is T, not (T) -> T. How can this be accomplished? Is this a better way of going about closure composition?
Edit: My original answer misunderstood what your problem was. But seeing as my original answer might be useful to future readers, I'll leave it at the bottom.
Your compose function is nearly there! b(a) does not compile because MyClosure does not take another MyClosure. b(a) is invoking the closure ("function application"). not composition. Since compose returns a closure, why not return a closure? A typical closure looks like this in Swift:
{ (param) in return doSomethingTo(param) }
So let's return that!
return { (x) in return b(a(x)) }
This can be simplified to:
{ b(a($0)) } // "return" can be omitted as well!
This page (among other things) tells you how and when you can simplify closure syntaxes.
Original answer:
Using reduce is the correct choice here. The reduction operation is composition, so let's write a compose function first:
func compose<T>(_ x: #escaping (T) -> T, _ y: #escaping (T) -> T) -> (T) -> T {
{ y(x($0)) } // or { x(y($0)) } if you want it the other way
}
Then, we reduce. What's the identity? The identity is something that has these properties:
compose(identity, anything) == anything
compose(anything, identity) == anything
What function does that? The identity function!
So we get:
func reduceClosures<T>(_ closures: [(T) -> T]) -> (T) -> T {
closures.reduce({ $0 }, compose)
}

Why does an instance method have this type in Swift?

Given this code:
struct Foo {
func f() {}
}
let f = Foo.f // (Foo) -> () -> ()
Why does f have the type (Foo) -> () -> () and not (Foo) -> ()? Wouldn’t it make sense for instance methods like Foo.f to be directly interchangeable with free functions of type (Foo) -> …?
Why does f have the type (Foo) -> () -> () and not (Foo) -> ()?
That's just currently how unapplied instance method references are implemented; they're curried functions that follow the model of "give me an instance, and I'll give you back a partially-applied instance method" (partially applied with that instance).
However this is problematic in some areas, firstly because it's generally more useful for them to be of the form (Self, Args...) -> Ret, but also more importantly because it because it leads to issues around mutating methods. These end up looking like (inout Self) -> (Args...) -> Ret with the current system, which is problematic because the window of mutation for inout only lasts for the duration of the call.
This means the following currently compiles, but is actually undefined behaviour:
struct S {
var i: Int
mutating func increment() {
i += 1
}
}
var s = S(i: 0)
let unappliedIncrement = S.increment
let increment = unappliedIncrement(&s)
increment() // undefined behaviour
These are the main motivations behind SE-0042, which will change unapplied instance method references from being of the form (Self) -> (Args...) -> Ret to being of the form (Self, Args...) -> Ret (and with inout, Self will be inout Self – allowing the mutation of the instance without UB).
This proposal is yet to be implemented, but once it is, assuming empty parameter lists get flattened out (so you don't end up with a trailing Void parameter), Foo.f will indeed be of type (Foo) -> Void.
It's because, by saying this:
let f = Foo.f
you've described f as a class method, Foo.f. But in your declaration of Foo, f is an instance method. You have thus accidentally discovered the deep dark secret that instance methods are class methods in disguise; you are seeing the signature of the secret class method.
If you had said
let f = Foo().f
you would have gotten the expected result.

Swift generic function with clousure

I've the following generic function (not part of any class):
func execFuncWithGenericParameter<T, U>(f: (T) -> U){
print(f("Hello World"))
}
I'd like to call this function in with a closure like this:
execFuncWithGenericParameter(f: { (p: String) -> Int in
print(p)
return 4711
})
But the compiler (iPad Swift Playground) tells me that "(String) -> U is not convertible to (T) -> U".
Naturelly I've done done some investigation and was the opinion that the Compiler automatically will infer the types.
Thanks.
The types are being inferred as far as the nature of f: (T) -> U is concerned. The problem is the call to f inside your first method.
Ask yourself: what if T were not String? Then f("Hello world") would be illegal. That is the quandary you've left the compiler with — and it rightly refuses to deal with it.
Here's a legal version:
func execFuncWithGenericParameter<T,U>(f: ((T) -> U), param:T){
f(param)
}
execFuncWithGenericParameter(f: { (p: String) -> Int in
print(p)
return 4711
}, param:"Hello")
Now the first method knows that param will be a T, so all is well. And in the second method, when we call the first method, T is String and param is a String, so it compiles (and runs, and prints).

Infer closure return type from closure body when working with generics

I think best if I start with an example:
class Test<T> {
func test(closure: (T) -> Void) { }
func test(closure: (T) -> T) { }
func test(closure: (T) -> Test<T>) { }
}
Test<Int>().test { a in }
The code above gives the following error:
error: ambiguous use of 'test'
This is because the Swift compiler doesn't know to which one of the three methods is should map the call to. But from the closure body it's quite clear that it returns a Void, so it should pick the first method.
Looks like the Swift compiler cannot determine to which method overload to map the call to based on the closure body. If I explicitly specify the closure signature, then the problem goes away:
Test<Int>().test { (a: Int) -> Void in }
My question is: can I somehow instruct Swift to pick-up the correct overload for short-hand closure expressions like the one in discussion, or will I have to explicitly declare the closure signature?
Actually, it seems that I was pushing the compiler limits too hard (as #Martin R pointed in the comments). The { a in } closure was kinda incomplete, since the compiler had no statements to infer the closure return type from.
This works:
Test<Int>().test { (a: Int) -> Void in () }
Same as the following:
func doNothing() { }
Test<Int>().test { (a: Int) -> Void in doNothing() }
In the above examples the compiler is provided with the minimum amount of information to determine which overload to pick.

How does a flatMap on a double-generic data-structure looks like?

I have the following (simple) data structure:
struct Work<Input, Output> {
let work: Input -> Output
}
This type represents work which can take an Input and turns in into a desired Output. I am trying to see whether this data structure conforms to some functional concepts like a functor or a monad.
Functor
extension Work {
func map<MoreOutput>(transform: Output -> MoreOutput) -> Work<Input, MoreOutput> {
return Work<Input, MoreOutput> {
return transform(self.work($0))
}
}
}
That seems to be correct as far as I am aware. I am able to write a map function which can turn Work<Input, Output> into Work<Input, MoreOutput>
Monad
I have trouble thinking of the definition for a flatMap (or fold) function for Work. The only thing I can come up with is the following:
extension Work {
func flatMap<MoreOutput>(transform: Work<Output, MoreOutput>) -> Work<Input, MoreOutput> {
return Work<Input, MoreOutput> { input in
return transform.work(self.work(input))
}
}
}
If you look up the flatMap definition for an Array in swift it looks like this (simplified):
func flatMap(transform: (Element) -> T?) -> [T]
This is a function where its argument is a function which transforms an Element into T and results an Array. I cannot think of a way to abstract this to the Work type.
From another functional book I found a general definition for flatMap as follows (on an object F holding type A):
func flatMap<B>(f: A -> F<B>) -> F<B>
which is a different definition of flatMap than Array seems to implement.
Can someone explain this difference to me? And is it even possible to define a 'correct' flatMap function on Work? Or does Work not satisfy the properties to be a Monad?
** Edit
Thanks phg for so much useful info. I've tried to do the Profunctor definition:
Making Work a Profunctor:
extension Work {
func diMap<A, B>(fa: A -> Input, fb: Output -> B) -> Work<A, B> {
return Work<A, B> { arg in
let input = fa(arg)
let output = self.work(input)
return fb(output)
}
}
}
Does that look right to you?
This:
func flatMap<B>(f: A -> F<B>) -> F<B>
is what you want flatMap to look like; it's the monad's usual "bind" operation. Specialized for functions over the second argument, you get the so-called Reader monad:
extension Work {
func flatMap<MoreOutput>(g: Output -> Work<Input, MoreOutput>) -> Work<Input, MoreOutput> {
// (Reader f) >>= g = Reader $ \x -> runReader (g (f x)) x
return Work<Input, MoreOutput> {
g(self.work($0)).work($0)
}
}
}
Note: I actually don't speak Swift, this code was just guessing -- hence the included Haskell original. Feel free to edit in a corrected version.
Now to the other definition:
func flatMap(transform: (Element) -> T?) -> [T]
I suppose T? means something like "optional T" or "nullable T". This is not what we usually understand as a monadic function, but it is related. Indeed, there has been a question about such "generalized flatMaps". The answer is, that if two monads are compatible, i.e., there exists a monad morphism F<A> -> G<A> preserving monadic structure, it makes sense to define
func wrappedFlatMap<B>(f: A -> F<B>) -> G<B>
which is probably exactly what is happening here for the "option type" and the list type, where the morphism is logically just
Just x ~> [x]
Nothing ~> []