Experiments with Swift 3 operator precedence and partial function application - swift

So I've been messing around with partial function application i.e.
func partial<A, B, C>(_ #escaping f: (A, B) -> C, _ a: A) -> (_ b: B) -> C {
return { b in f(a, b) }
}
which is cool. I can do let equals3 = partial(==, 3) and everything works as expected
now when I try to make an operator for this in Swift 3 things are getting not so cool
infix operator •
func • <A, B, C>(_ #escaping lhs: (A, B) -> C, _ rhs: A) -> (_ b: B) -> C {
return { b in lhs(rhs, b) }
}
let equals3 = (== • 3) raises compiler message Unary operator cannot be separated from it's operand
so I thought ok, maybe it's getting confused because these two operators == and • are next to each other without declaring any precedence rules (even though in my understanding == shouldn't be considered an operator in this situation)
but still, doing
precedencegroup FunctionApplicationPrecedence {
higherThan: ComparisonPrecedence // the precedencegroup == belongs to
}
infix operator • : FunctionApplicationPrecedence
let equals3 = (== • 3) doesn't compile and raises the same message
am I misunderstanding something here?

So I've been messing around with partial function application
Yeah… that's probably going to go poorly… Swift lacks lots of features you would want to make that work well, and has steadily removed features (like currying syntax) that it even had. This is one of the great "you're fighting Swift" roads that we all walk down at one point or another.
That said, this has an easy fix, not unlike the fix in Haskell. You just have to put parens around the operator so the parser doesn't lose its mind. (It's probably worth opening a JIRA about the diagnostic. You should get a better error.)
let equals3 = ((==) • 3)
Or more simply:
let equals3 = (==) • 3
But oh, Swift will fight you if you keep going down this road. It'll all be roses until it's all SIG11s and expression too complex and "what do you mean there aren't higher-kinded types?"
But it's a fun road until you start throwing things, so curry on.
(If you want to see my latest walk way too far down this road, here's FP in Swift. It... works... kinda. But you fight the compiler the whole way.)

Related

Swift 5.2 tuple destructuring in closure has inconsistent behaviors

I ran into a weird tuple destructuring problem in Swift 5.2.
I thought tuple destructuring didn't work inside a closure parameter since some time ago.
And indeed, the following does not work:
let expected: ((Int, Int)) -> Void = { a, b in // does not compile
print(a, b)
}
However, I noticed that all of the below work:
func weird(closure: #escaping ((Int, Int)) -> Void) {
closure((1, 3))
}
// I can understand this
weird { print($0.0 + $0.1) }
weird { a, b in print(a + b) }
// Surprise!
weird { print($0 + $1) }
weird { p in print(p.0 + p.1) }
Did the last two examples worked before Swift 5.2? Is this behavior documented somewhere?
It is related to this proposal, which was once accepted in Swift 4.0.
SE-0110 Distinguish between single-tuple and multiple-argument function types
So, two of your examples (not last two though) caused error in a certain version of Swift, but Swift team found some unacceptable regression in this implementation.
Additional Commentary
And since a certain version of Swift (I do not remember the exact version, it might have been 4.0.x or 4.1), you can pass two argument closure to the parameter of function type taking a single tuple.
And recently, this exception is confirmed to be a part of SE-0110 and if some more modification is needed, a new proposal will be made and go through the usual Swift Evolution process.
Update on SE-0110 and SE-0155
the original proposal as reviewed did not include the special-case
conversion from (T, U, ...) -> V to ((T, U, ...)) -> V for function
arguments. In response to community feedback, this conversion was
added as part of the Core Team's acceptance of the proposal.
The Swift book may not have clear explanation of this behavior, but it surely is documented.

Generic Where Clause Ambiguity with Associated Types in Swift

I was writing some example code in a playground and wanted a function that returns the distance between two values, both of which conform to the Strideable protocol in Swift so that I could use the distance(to other: Self) -> Self.Stride function. My implementation was as follows:
func distanceFrom<T: Strideable, U>(_ a: T, to b: T) -> U where T.Stride == U
{
return a.distance(to: b)
}
After observing this function for a while, I realized that I wasn't sure which Stride was being used in the where clause, the one from a or from b. From what I understand it would be possible for a and b to define different associated types for Stride. Also I haven't made any statements to ensure that a.Stride == b.Stride, although I understand that I could expand my where clause to do so.
So, which one would get used to check equivalence to U? To be clear, the question isn't about this particular code block, but rather any situation in which this ambiguity would exist.
a and b are the same type. If you wanted them to be different Strideable types you would add another generic parameter conforming to Strideable such that the function signature appears as follows:
func bar<T: Strideable, V: Strideable, U>(_ a: T, to b: V) -> U where T.Stride == U, V.Stride == U {
return a.distance(to: a) //Trivial return statement (see explanation below)
}
Although the aforementioned code would compile, return a.distance(to: b) would not compile because they (a and b) are different types and the definition of distance in Swift3 is public func distance(to other: Self) -> Self.Stride (note the use of Self which restricts other to the same type as the Strideable upon which this function is called). In conclusion, although you could make a and b different types, for your application it would not make sense to do so.
As further evidence for not being able to call your original posted code with different types please see the attached
Playground screenshot which shows an error when using different types.
However, this works fine in the playground.
func distanceFrom<T: Strideable, U>(_ a: T, to b: T) -> U where T.Stride == U {
return a.distance(to: b)
}
let doubleFoo: Double = 4.5
let intFoo: Double = 4
let g = distanceFrom(doubleFoo, to: intFoo) // gives me a double of -0.5
I hope this helps.

Initializing an enum of generic type from rawValue

I'm experimenting with custom operators in Swift (EXPERIMENTING. I do not need a lecture about why custom operators are bad) and I thought, hmm, EnumType(rawValue:) is a bit long. Maybe I could fix this with an operator? So I wrote:
infix operator ∑
func ∑ <T,U:RawRepresentable>(lhs:T,rhs:U.Type) {
rhs(rawValue: lhs)
}
Which as intended would be used like this example:
enum DiceResult: Int {
case one = 1, two, three, four, five, six
}
let roll = 1 ∑ DiceResult //DiceResult.one
But the code I wrote gives me this error:
Non-nominal type 'U' does not support explicit initialization
Honestly I didn't expect what I wrote to work anyway, and I'm not even certain something like what I'm trying to write is at all possible in Swift. Can anybody shed some light whether I can do something like this, and if so how?
The main error is that you treat the operand types U, T as independent. But the type of the left operand must be the RawValue type of the right operand. So this would compile:
infix operator ∑
func ∑ <U: RawRepresentable>(lhs: U.RawValue, rhs: U.Type) -> U? {
return rhs.init(rawValue: lhs)
}
You can then use it as
enum DiceResult: Int {
case one = 1, two, three, four, five, six
}
let roll = 1 ∑ DiceResult.self
.self is required to access the type as a value.
Unfortunately this is not much shorter than
let roll = DiceResult(rawValue: 1)

Type coercion issue in Swift

EDIT: This works absolutely fine in Swift 3, which we should all be using by now :)
If I have two protocols, X and Y where Y implements X, why can't I assign an array of Y to a variable with the type [X]?
Even more curiously, I can convert it one by one into an array of X, and that compiles fine.
protocol X { }
protocol Y: X { }
// Make a test array of Y
extension String: Y { }
let a: [Y] = [ "Hello" ]
// Make it into an array of X - this works absolutely fine
let b: [X] = [ a[0] as X ]
// Why won't this cast work?
let c: [X] = a as [X]
I thought that given Y does everything X can do, this assignment should be fine (yea, I lose some type information, but it should at least compile!)
Any ideas?
EDIT: The current answer points out that it's a dangerous thing to do if you are using mutable arrays - which I didn't get but do now :) However, if my arrays are all immutable why won't Swift let this happen? Even if c is a mutable array (i.e. var c = a as [X]) why won't Swift copy it, leaving a intact?
This doesn't work because it could create a few problems. For example:
var squares: Array<Square> = Array<Square>()
(squares as [Shape]).append(Circle())
Now we have a circle in our Array of Squares. We don't want that, so the compiler doesn't let us. In other languages like Scala you can specify generics to be covariant, contravariant or invariant.
If Swift would let you use covariant generics an Array<Square> would be a subtype of Array<Shape>.
If using contravariance an Array<Square> would be a supertype(!) of Array<Shape>.
But when using invariant generics, neither is the subtype of neither.
The easiest way to do it in your case would probably be this:
let c = a.map{$0 as X}
Now c is of type [X].
For more information on type variance and why it can be problematic visit, you can visit this wiki page.
EDIT: After further back and forth, it seems the real problem is, that Protocols allow default implementations and can therefore cause problems. Your code will compile flawlessly when using classes. Here's some code that could potentially lead to problems with protocols:
protocol Shape {
func surfaceArea() -> Double
}
extension Shape {
func surfaceArea() -> Double {
return 0.0
}
}
protocol Circle : Shape {
func getRadius() -> Double
}
extension Circle {
func surfaceArea() -> Double {
return getRadius() * getRadius() * 3.14
}
}
Now, when we upcast between these two protocols, the surfaceArea() method returns different values, and Swift doesn't allow it.
Try the same thing with classes, instead of protocols and Swift won't have any problems compiling your current code. This is, to me, kind of a weird decision by the Swift team, but I still think the best way to mitigate is to just use
let c = a.map{$0 as X}

Are there any possible explicit uses of instances (values) of empty tuples (), i.e., of instances of typealias 'Void'?

Question:
Are there any possible explicit uses for the empty tuple (), as a value (and not as a type) in Swift 2.x?
I know that these empty tuples can be used in the standard sense to define void functions. When I mistakenly defined a variable with a empty tuple value var a = () (of type ()), I started wondering if these empty tuple values can be used in some context. Does anyone know of such an application?
Example: possible application with array and optionals?
As an example, we can create an optional array of empty tuples that, naturally, can only hold either nil or ():
/* Optionals */
var foo: ()? = ()
print(foo.dynamicType) // Optional<()>
var arr : [()?] = [foo]
for i in 2...8 {
if i%2 == 0 {
arr.append(nil)
}
else {
arr.append(foo)
}
}
print(arr) // [Optional(()), nil, Optional(()), ... ]
With the small memory footprint of empty tuple, this could seem neat for micro-memory-management for a "boolean nil/not nil", but since type Bool have the same small footprint, I can't really see any direct use here, even in the (unlike) scenario that we really need to go bit-low optimization on our operations.
Perhaps I'm just chasing my own tail with some narrow unusable applications, but anyway: are there any possible explicit uses for these void () beings (as instances, not types)?
There are lots of places that () can be useful when playing around with "CS" problems, which often have the form "implement X using Y even though you really already have X." So for instance, I might say, implement Set using Dictionary. Well, a Dictionary is a Key/Value pair. What should the type of the Value be? I've actually seen this done in languages that have Dictionaries but not Sets, and people often use 1 or true as the value. But that's not really what you mean. That opens up ambiguity. What if the value is false? Is it in the set or not? The right way to implement Set in terms of Dictionary is as [Key: ()], and then you wind up with lines of code like:
set[key] = ()
There are other, equivalent versions, like your Optional<()>. I could also implement integers as [()] or Set<()>. It's a bit silly, but I've done things like that to explore number theory before.
That said, these are all almost intentionally impractical solutions. How about a practical one? Those usually show up when in generic programming. For example, imagine a function with this kind of form:
func doThingAndReturn<T>(retval: T, f: () -> Void) -> T {
f()
return retval
}
This isn't as silly as it sounds. Something along these lines could easily show up in a Command pattern. But what if there's no retval; I don't care about the return? Well, that's fine, just pass a () value.
func doThing(f: () -> Void) {
doThingAndReturn((), f: f)
}
Similarly, you might want a function like zipMap:
func zipMap<T, U>(funcs: [(T) -> U], vals: [T]) -> [U] {
return zip(funcs, vals).map { $0($1) }
}
This applies a series of functions that take T to values of type T. We could use that even if T happens to (), but we'd have to generate a bunch of () values to make that work. For example:
func gen<T>(funcs: [() -> T]) -> [T] {
return zipMap(funcs, vals: Array(count: funcs.count, repeatedValue: ()))
}
I wouldn't expect this to come up very often in Swift because Swift is mostly an imperative language and hides its Void in almost all cases. But you really do see things like this show up in functional languages like Scala when they bridge over into imperative programming.
Suppose you have two functions overloading the same name:
func foo()
func foo() -> Int
The first doesn't return anything, the second returns some kind of value. Attempting to call either of these will in most cases get you a compiler error about ambiguity.
foo()
let a = foo()
You'd think that the compiler would know that the first call unambiguously refers to the first function, because it assumes no return value. But in actuality, the return type of a function with no declared return type is Void, or (). So the first call is actually more like this:
let _ = foo()
And absent a type annotation for the discarded lvalue, the compiler can't infer which foo to call. You can use explicit type annotations to disambiguate:
let b: Void = foo()
let c: Int = foo()
Okay, it's not a very great or common use case for Void, because it's a situation you'd tend to avoid getting into in the first place. But you asked for a use... and it is a use of () as a value and not just a type, because you can retrieve it from b after assignment (for all the good that does you).
Just beware, when you look deeply into the Void, the Void also looks into you. Or something like that.