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

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 ~> []

Related

Definition of flatMap in Swift

I was studying a functor and monad. So I got to know that a functor uses map and a monad uses flatMap, and also that definition of map and flatMap looks like below.
enum Box<T> {
case some(T)
case empty
}
extension Box {
func map<U>(_ f: #escaping (T) -> U) -> Box<U> {
// ...
}
}
extension Box {
func flatMap<U>(_ f: (T) -> Box<U>) -> Box<U> {
// ...
}
}
I totally got those are using different f parameter(Thanks for this article).
Then, I just wanted to check definition of map and flatMap in Optional, Result and Array. Because I heard those are monad as well. In Optional and Result, the definition looks like same as custom map and flatMap above.
But in Array, does not.
func map<T>(_ transform: (Element) throws -> T) rethrows -> [T]
func flatMap<SegmentOfResult>(_ transform: (Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Element] where SegmentOfResult : Sequence
I'm bit confused now. Because I knew a monad apply a function that returns wrapped value to wrapped value, so I expected the definition of flatMap looking like below(definitely wrong).
func flatMap<T>(_ transform: (Element) throws -> [T]) rethrows -> [T]
But It's not anyway.
Am I missing something? Where is the point that I misunderstood?
You were expecting
func flatMap<T>(_ transform: (Element) throws -> Array<T>) rethrows -> Array<T>
for Array.
If you look closely, the above is merely a special case of the signature that you found, when SegmentOfResult == Array<T>.
The flatMap in Array is defined not just for the case when SegmentOfResult == Array<T>, but also for any SegmentOfResult that is a Sequence.
Why? Because we would like to define functions so that they work on as many types as possible (i.e. as general as possible). It turns out that flatMap would also work if the function mapped to any Sequence. That is, it doesn't depend on the fact that the function returns specifically an Array. It only depends on the fact that the function returns some kind of a Sequence. Check out how flatMap is implemented here if you are interested.
For the same reason, flatMap isn't just available on Array, it's available on any type that conforms to Sequence!

Swift optional promotion vs generic overload resolution

Please consider the following code:
protocol P {}
class X {}
class Y: P {}
func foo<T>(_ closure: (T) -> Void) { print(type(of: closure)) }
func foo<T>(_ closure: (T) -> Void) where T: P { print(type(of: closure)) }
let xClosure: (X?) -> Void = { _ in }
foo(xClosure) // prints "(Optional<X>) -> ()"
let yClosure: (Y?) -> Void = { _ in }
foo(yClosure) // prints "(Y) -> ()"
Why does the foo(yClosure) call resolve to the version of foo constrained to T: P?
I understand why that version prints what it prints,
what I don't see is why it gets called instead of the other one.
To me it seems that the non-P version would be a better match for T == (Y?) -> Void.
Sure, the constrained version is more specific, but it requires conversion
(an implicit conversion from (Y?) -> Void to (Y) -> Void),
while the non-P version could be called with no conversion.
Is there a way to fix this code in a way such that the P-constrained version gets called
only if the parameter type of the passed-in closure directly conforms to P,
without any implicit conversions?
Specificity seems to always trump variance conversions, according to my experiments. For example:
func bar<T>(_ x: [Int], _ y: T) { print("A") }
func bar<T: P>(_ x: [Any], _ y: T) { print("B") }
bar([1], Y()) // A
bar is more specific, but requires a variance conversion from [Int] to [Any].
For why you can convert from (Y?) -> Void to (P) -> Void, see this. Note that Y is a subtype of Y?, by compiler magic.
Since it is so consistent, this behaviour seems to be by design. Since you can't really make Y not a subtype of Y?, you don't have a lot of choices if you want to get the desired behaviour.
I have this work around, and I admit it's really ugly - make your own Optional type. Let's call it Maybe<T>:
enum Maybe<T> {
case some(T)
case none
// implement all the Optional methods if you want
}
Now, your (Maybe<Y>) -> Void won't be converted to (P) -> Void. Normally I wouldn't recommend this, but since you said:
in the real-world code where I encountered this, the closure has multiple params, any of them can be optional, so this would lead to a combinatorial explosion.
I thought reinventing Optional might be worth it.

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

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

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.

Lenses into Swift properties

Is there some way to automatically generate a getter/setter function pair for a property in a class in Swift? Something along the lines of a lens in Haskell.
I've been able to do the following manually:
class PropertyLens<U, T> {
let getter: U -> T
let setter: (U, T) -> ()
init(getter: (U -> T), setter: ((U, T) -> ())) {
self.getter = getter
self.setter = setter
}
func get(u: U) -> T {
return getter(u)
}
func set(u: U, t: T) {
setter(u, t)
}
}
// ...
let myPropertyLens = PropertyLens<MyClass, Int>(getter: { $0.myProperty }, setter: { $0.myProperty = $1 })
However, that becomes verbose, tedious, and more error-prone than I'd like. Is there a built-in feature I'm missing?
For the answer itself, so far (1.1) no language construct will substitute what you are doing (wrapping the access process of a stored property into a referenciable object).
For the opinion part of the answer, it looks like your code only works with public variables, which are nasty for they break basic encapsulation rules, is that correct?
You should give Sourcery a try. I have the same problem and I run into this tool, if you make a quick search you should easily find some already made templates for Sourcery that lets you generate lenses for your data types.