SE-0066 Reaction

Hi,

I missed the original thread, but here are my thoughts on SE-0066 right
after Chris's email ends with "thoughts?".

Concern 1:

I feel like we're forgetting about the functional programming syntax of
declaring function types like this:

A -> B -> C

for a function foo(a: A, b: B) -> C

This eliminates the ambiguity of what the parameter types are, and is more
legible (less paren hell) than adding parens like this:

(A,B) -> C

which for a function

foo(a: (A, B)) -> C

would look like this after the implementation of SE-0066:

((A,B)) -> C

instead of

(A,B) -> C

Concern 2:

There's also the potential to transform a function like this

A -> B -> C

into this

B -> C

after partial application, something which might not be totally irrelevant
to Swift in its future.

Here are a few contrived examples of function types showing the paren
version (order 66), the parens on the return type too, and the generic
functional programming version (right). I want to preface this with,
"Remember that Swift is an enjoyable experience because reading Swift is
pleasant."

66 | 66 return type | generic functional style |
--------------------+----------------------+--------------------------|
(A) -> B | (A) -> (B) | A -> B |

(A, B) -> C | (A, B) -> (C) | A -> B -> C |

((A, B)) -> C | ((A, B)) -> (C) | (A, B) -> C |

([A]) -> B | ([A]) -> (B) | [A] -> B |

([A], (B, C)) -> D | ([A], (B, C)) -> (D) | [A] -> (B, C) -> D |

([A], [B]) -> [C] | ([A], [B]) -> ([C]) | [A] -> [B] -> [C] |

(([A], [B])) -> C | (([A], [B])) -> (C) | ([A], [B]) -> C |

- Mish

Concern 1:
I feel like we're forgetting about the functional programming syntax of declaring function types like this:

A -> B -> C

for a function foo(a: A, b: B) -> C

This analogy doesn’t exist in Swift, languages like Haskell have auto-currying behavior like this, but Swift does not.

This eliminates the ambiguity of what the parameter types are, and is more legible (less paren hell) than adding parens like this:

(A,B) -> C

which for a function

foo(a: (A, B)) -> C

would look like this after the implementation of SE-0066:

((A,B)) -> C

instead of

(A,B) -> C

I’m not sure what the actual concern you’re pointing out here. However, you are forgetting the argument labels. Your foo example will have type:

(a: (A,B)) -> C

More to the point thought, this example is *exactly* why SE-0066 is the right thing to do. You cannot currently write the type of “foo” as "(A,B) -> C”. (with or without labels), because of the grammar ambiguities that SE-0066 fixes.

That said, it is likely that I’m totally missing your point here, can you please restate your concern?

Concern 2:

There's also the potential to transform a function like this

A -> B -> C

into this

B -> C

after partial application, something which might not be totally irrelevant to Swift in its future.

This isn’t affected by SE-0066 - what is your concern? With SE-0066, the transformation is:

(A) -> (B) -> C
into:
(B) -> C

Please keep in mind that SE-0066 doesn’t change the type system, it just adds parens in a very narrow case.

Here are a few contrived examples of function types showing the paren version (order 66), the parens on the return type too, and the generic functional programming version (right). I want to preface this with, "Remember that Swift is an enjoyable experience because reading Swift is pleasant.”

0066 does not affect the return type of a function.

-Chris

···

On Apr 26, 2016, at 10:52 AM, Mishal Awadah via swift-evolution <swift-evolution@swift.org> wrote:

> Concern 1:
> I feel like we're forgetting about the functional programming syntax of
declaring function types like this:
>
> A -> B -> C
>
> for a function foo(a: A, b: B) -> C

This analogy doesn’t exist in Swift, languages like Haskell have
auto-currying behavior like this, but Swift does not.

Indeed, my point is that this proposal drives the distance further from
this analogy, which is a nice one, because function application is still
relevant in Swift, and may be more so in the future. That is to say, this
is closing a functional programming door. I am contrasting this proposal to
Haskell's type system, not the existing Swift one, to increase the
awareness of the direction this is going.

In summary: I am concerned that by doing this we will never do the
Haskell-style type annotations, which feel more at home in Swift.

Obviously, if the Haskell-style annotations are a given "we are never going
to adopt this in Swift", then I cannot argue with the increased clarity
that 0066 provides, despite the unpleasant parenthesis proliferation it
will cause.

>
> This eliminates the ambiguity of what the parameter types are, and is
more legible (less paren hell) than adding parens like this:
>
> (A,B) -> C
>
> which for a function
>
> foo(a: (A, B)) -> C
>
> would look like this after the implementation of SE-0066:
>
> ((A,B)) -> C
>
> instead of
>
> (A,B) -> C

I’m not sure what the actual concern you’re pointing out here. However,
you are forgetting the argument labels. Your foo example will have type:

(a: (A,B)) -> C

More to the point thought, this example is *exactly* why SE-0066 is the
right thing to do. You cannot currently write the type of “foo” as "(A,B)
-> C”. (with or without labels), because of the grammar ambiguities that
SE-0066 fixes.

That said, it is likely that I’m totally missing your point here, can you
please restate your concern?

I'm confused, I created this function and got the type without argument
label annotation.

func happy(a: (Int, Int)) -> String {

    return "Happy"

}

print(happy.dynamicType)

// prints: (Int, Int) -> String

The concern is that rather than move towards a more Haskell-like syntax
(which removes ambiguity of tuple params over multiple params as well) this
is adding more parens and making it look less pleasant to read. Contrast
the types of these functions in the Haskell-Style, and the proposed 0066
style:

Haskell Style: (Int, Int) -> String
0066 Style: ((Int, Int)) -> String

The Haskell Style would remove the ambiguity against a function like this:

func unhappy(a: Int, b: Int) -> String {

    return "Unhappy"

}

print(unhappy.dynamicType)

//prints:(Int, Int) -> String

Haskell Style: Int -> Int -> String
0066 Style: (Int, Int) -> String

Now compare these two functions in their respective styles, which one is
clearer to parse at glance?

// haskell style

// happy: (Int, Int) -> String

// unhappy: Int -> Int -> String

// 0066 style

// happy: ((Int, Int)) -> String

// unhappy: (Int, Int) -> String

Perhaps I am jaded from spending time in a functional programming world
(although really not that much), but it is definitely going to take me a
while to see that unhappy is accepting 2 separate params, rather than a
single tuple params. I think this is more because of how we represent tuple
types (like array types) as (Int, Int) or [Int] everywhere else.

In the wild, a tuple type looks like this:

foo: (Int, Int)

but for functions we'll use

fooFunc: ((Int, Int)) -> ()

> Concern 2:
>
> There's also the potential to transform a function like this
>
> A -> B -> C
>
> into this
>
> B -> C
>
> after partial application, something which might not be totally
irrelevant to Swift in its future.

This isn’t affected by SE-0066 - what is your concern? With SE-0066, the
transformation is:

(A) -> (B) -> C
into:
(B) -> C

Please keep in mind that SE-0066 doesn’t change the type system, it just
adds parens in a very narrow case.

I was thinking about partial function application in the context of
ordinary functions (i.e. not those that explicitly return functions as
well), should that ever be an interesting direction for Swift to head into.

Otherwise, if we look at functions that explicitly return functions, you
could still get a nice function type in the Haskell way if you paren the
return type:

A -> (B -> C)

which reads more simply to me.

(A) -> (B) -> C isn't as clear to parse in this way, but with practice it
doesn't seem like it would be hard to get used to. Perhaps some confusing
instances would be:

(A) -> (B) -> (C) where (C) is a single tuple of type C.

- Mish

···

On Tue, Apr 26, 2016 at 11:23 AM, Chris Lattner <clattner@apple.com> wrote:

On Apr 26, 2016, at 10:52 AM, Mishal Awadah via swift-evolution < > swift-evolution@swift.org> wrote:

>
>
> Here are a few contrived examples of function types showing the paren
version (order 66), the parens on the return type too, and the generic
functional programming version (right). I want to preface this with,
"Remember that Swift is an enjoyable experience because reading Swift is
pleasant.”

0066 does not affect the return type of a function.

-Chris

This analogy doesn’t exist in Swift, languages like Haskell have auto-currying behavior like this, but Swift does not.

Indeed, my point is that this proposal drives the distance further from this analogy, which is a nice one, because function application is still relevant in Swift, and may be more so in the future. That is to say, this is closing a functional programming door. I am contrasting this proposal to Haskell's type system, not the existing Swift one, to increase the awareness of the direction this is going.

Hi Mish,

I’m also fond of Haskell and the MLs, and I appreciate many of the choices that they made in the context of their languages. However, there are a large number of deep differences between the type system in Swift and the type system in Haskell that motivate the current behavior we have in Swift.

SE-0066 is a very narrow proposal - it only affects syntax, not semantics. The type system semantics that you seem interested in are unlikely to happen regardless of the syntax changes SE-0066 imply, and SE-0066 doesn’t have anything to do with that.

-Chris

···

On Apr 26, 2016, at 3:37 PM, Mishal Awadah <a.mamish@gmail.com> wrote:

In summary: I am concerned that by doing this we will never do the Haskell-style type annotations, which feel more at home in Swift.

Obviously, if the Haskell-style annotations are a given "we are never going to adopt this in Swift", then I cannot argue with the increased clarity that 0066 provides, despite the unpleasant parenthesis proliferation it will cause.

>
> This eliminates the ambiguity of what the parameter types are, and is more legible (less paren hell) than adding parens like this:
>
> (A,B) -> C
>
> which for a function
>
> foo(a: (A, B)) -> C
>
> would look like this after the implementation of SE-0066:
>
> ((A,B)) -> C
>
> instead of
>
> (A,B) -> C

I’m not sure what the actual concern you’re pointing out here. However, you are forgetting the argument labels. Your foo example will have type:

(a: (A,B)) -> C

More to the point thought, this example is *exactly* why SE-0066 is the right thing to do. You cannot currently write the type of “foo” as "(A,B) -> C”. (with or without labels), because of the grammar ambiguities that SE-0066 fixes.

That said, it is likely that I’m totally missing your point here, can you please restate your concern?

I'm confused, I created this function and got the type without argument label annotation.

func happy(a: (Int, Int)) -> String {
    return "Happy"
}

print(happy.dynamicType)
// prints: (Int, Int) -> String

The concern is that rather than move towards a more Haskell-like syntax (which removes ambiguity of tuple params over multiple params as well) this is adding more parens and making it look less pleasant to read. Contrast the types of these functions in the Haskell-Style, and the proposed 0066 style:

Haskell Style: (Int, Int) -> String
0066 Style: ((Int, Int)) -> String

The Haskell Style would remove the ambiguity against a function like this:

func unhappy(a: Int, b: Int) -> String {
    return "Unhappy"
}

print(unhappy.dynamicType)
//prints:(Int, Int) -> String

Haskell Style: Int -> Int -> String
0066 Style: (Int, Int) -> String

Now compare these two functions in their respective styles, which one is clearer to parse at glance?

// haskell style
// happy: (Int, Int) -> String
// unhappy: Int -> Int -> String

// 0066 style
// happy: ((Int, Int)) -> String
// unhappy: (Int, Int) -> String

Perhaps I am jaded from spending time in a functional programming world (although really not that much), but it is definitely going to take me a while to see that unhappy is accepting 2 separate params, rather than a single tuple params. I think this is more because of how we represent tuple types (like array types) as (Int, Int) or [Int] everywhere else.

In the wild, a tuple type looks like this:

foo: (Int, Int)

but for functions we'll use

fooFunc: ((Int, Int)) -> ()

> Concern 2:
>
> There's also the potential to transform a function like this
>
> A -> B -> C
>
> into this
>
> B -> C
>
> after partial application, something which might not be totally irrelevant to Swift in its future.

This isn’t affected by SE-0066 - what is your concern? With SE-0066, the transformation is:

(A) -> (B) -> C
into:
(B) -> C

Please keep in mind that SE-0066 doesn’t change the type system, it just adds parens in a very narrow case.

I was thinking about partial function application in the context of ordinary functions (i.e. not those that explicitly return functions as well), should that ever be an interesting direction for Swift to head into.

Otherwise, if we look at functions that explicitly return functions, you could still get a nice function type in the Haskell way if you paren the return type:

A -> (B -> C)

which reads more simply to me.

(A) -> (B) -> C isn't as clear to parse in this way, but with practice it doesn't seem like it would be hard to get used to. Perhaps some confusing instances would be:

(A) -> (B) -> (C) where (C) is a single tuple of type C.

- Mish

>
>
> Here are a few contrived examples of function types showing the paren version (order 66), the parens on the return type too, and the generic functional programming version (right). I want to preface this with, "Remember that Swift is an enjoyable experience because reading Swift is pleasant.”

0066 does not affect the return type of a function.

-Chris

SE-0066 is a very narrow proposal - it only affects syntax, not
semantics. The type system semantics that you seem interested in are
unlikely to happen regardless of the syntax changes SE-0066 imply, and
SE-0066 doesn’t have anything to do with that.

It is most disappointing to read these sorts of statements.

One of the things that I have noticed over the last year or so of
working with Swift is a trend in the community of libriaries being
written for Swift towards some of these "system semantics" (i.e.,
functional paradigms) like applicatives and such.

Granted I may have a selection bias towards these sorts of libraries.
That is, I tried one library that did some of this stuff so then I
tried more. Eventually stumbling into an enclave of functional
practioners of Swift. I'm willing to admit that I have not conducted a
scientific survey.

But from my vantage we have a minority of Swift users participating in
these evolution discussions. Albeit, judging from the e-mail volume,
an extremely _vocal_ minority. I worry that these things become an
echo chamber and those not involved will look at some of the "writing
on the wall" and think differently about Swift going forward. Indeed
for those people they may look at Swift 3 and say "I did not leave
Swift; Swift left me."

What is more is that those not participating in these discussions now
may leave them with no recourse to be heard. Because apparently Swift 3
is a do-or-die release (or as the author of this evolution put it: "It
is now or never."). I wonder what portion of Swift developers, the ones
who want to see Swift be their go-to language for the forseable future,
understand the implications or justifications for a Swift 3 release.

All that having been said, I get it, decisions are made by those who
show up. Roger that. I also understand and agree with the desire to make
Swift its own language. To show restraint at the urge to turn the
language into a hodge podge of the "greatest hits" of language
paradigms. I sincerely appreciate the difficulty of the task for the
Swift core team.

I realized at the end that I do not really have a point. Apparently I'm
feeling philosphical this Wednesday morning.

I hope I’m coming across clearly here. What I’m trying to say is that there are a lot of reasons that the Swift type system works the way it does (e.g. inout has very specific behavior that doesn’t work when partially applied, we have specific promotion rules that apply only in argument lists etc). These reasons and features are certainly debatable, but have nothing to do with SE-0066, therefore they seem out of scope for a discussion of SE-0066 to go into.

-Chris

···

On Apr 27, 2016, at 6:05 AM, Ryan Lovelett <swift-dev@ryan.lovelett.me> wrote:

SE-0066 is a very narrow proposal - it only affects syntax, not semantics. The type system semantics that you seem interested in are unlikely to happen regardless of the syntax changes SE-0066 imply, and SE-0066 doesn’t have anything to do with that.

It is most disappointing to read these sorts of statements.

One of the things that I have noticed over the last year or so of working with Swift is a trend in the community of libriaries being written for Swift towards some of these "system semantics" (i.e., functional paradigms) like applicatives and such.

I initially had similar concerns to Mishal, but I worked my way through it
and found I was wrong.

In current Swift you can have a function:
A -> B -> C

Adding brackets for clarity, that is equivalent to this (current Swift):
A -> (B -> C)

After this proposal this will become:
(A) -> ((B) -> C)

Which can also be expressed (with proposal):
(A) -> (B) -> C

I don't think this is making it harder to do what you want. I think that's
what Chris meant. Please correct me if I'm wrong Chris :)

By my interpretation it is just removing the syntactic ambiguity between:
* a single argument that is a tuple of type: (A, B, C)
* multiple arguments: A, B, C

This is a small change with a big win.

···

On Wednesday, 27 April 2016, Ryan Lovelett via swift-evolution < swift-evolution@swift.org> wrote:

SE-0066 is a very narrow proposal - it only affects syntax, not
semantics. The type system semantics that you seem interested in are
unlikely to happen regardless of the syntax changes SE-0066 imply, and
SE-0066 doesn’t have anything to do with that.

It is most disappointing to read these sorts of statements.

One of the things that I have noticed over the last year or so of working
with Swift is a trend in the community of libriaries being written for
Swift towards some of these "system semantics" (i.e., functional paradigms)
like applicatives and such.

Granted I may have a selection bias towards these sorts of libraries. That
is, I tried one library that did some of this stuff so then I tried more.
Eventually stumbling into an enclave of functional practioners of Swift.
I'm willing to admit that I have not conducted a scientific survey.

But from my vantage we have a minority of Swift users participating in
these evolution discussions. Albeit, judging from the e-mail volume, an
extremely _vocal_ minority. I worry that these things become an echo
chamber and those not involved will look at some of the "writing on the
wall" and think differently about Swift going forward. Indeed for those
people they may look at Swift 3 and say "I did not leave Swift; Swift left
me."

What is more is that those not participating in these discussions now may
leave them with no recourse to be heard. Because apparently Swift 3 is a
do-or-die release (or as the author of this evolution put it: "It is now or
never."). I wonder what portion of Swift developers, the ones who want to
see Swift be their go-to language for the forseable future, understand the
implications or justifications for a Swift 3 release.

All that having been said, I get it, decisions are made by those who show
up. Roger that. I also understand and agree with the desire to make Swift
its own language. To show restraint at the urge to turn the language into a
hodge podge of the "greatest hits" of language paradigms. I sincerely
appreciate the difficulty of the task for the Swift core team.

I realized at the end that I do not really have a point. Apparently I'm
feeling philosphical this Wednesday morning.

Hey,

I'm inserting these opinions into almost every FP discussion, for which I'm sorry, but I believe it's important to remind everyone that there's the rest of us who will run away from Swift if it becomes too FP-y.

One of the things that I have noticed over the last year or so of working with Swift is a trend in the community of libriaries being written for Swift towards some of these "system semantics" (i.e., functional paradigms) like applicatives and such.

Just as an example of a different selection bias, I saw a couple of those, digged in for a little bit and then ran far, far away. I haven't seen any FP-related Swift libraries after that.

I absolutely don't have an impression that Swift has any affinity towards being functional. To me, it embraces mutability and higher-level object design aspects (like protocols) while taking only the bits of FP that are actually useful (e.g. collection methods).

I don't have any data, but I can bet that most software developers on iOS and Mac platforms welcome that, and don't really want the move towards FP.

A.

Thanks for the feedback Chris! I am happy with this proposal given the
discussion here.

- Mish

···

On Wed, Apr 27, 2016 at 7:01 AM, Andrew Bennett <cacoyi@gmail.com> wrote:

I initially had similar concerns to Mishal, but I worked my way through it
and found I was wrong.

In current Swift you can have a function:
A -> B -> C

Adding brackets for clarity, that is equivalent to this (current Swift):
A -> (B -> C)

After this proposal this will become:
(A) -> ((B) -> C)

Which can also be expressed (with proposal):
(A) -> (B) -> C

I don't think this is making it harder to do what you want. I think that's
what Chris meant. Please correct me if I'm wrong Chris :)

By my interpretation it is just removing the syntactic ambiguity between:
* a single argument that is a tuple of type: (A, B, C)
* multiple arguments: A, B, C

This is a small change with a big win.

On Wednesday, 27 April 2016, Ryan Lovelett via swift-evolution < > swift-evolution@swift.org> wrote:

SE-0066 is a very narrow proposal - it only affects syntax, not
semantics. The type system semantics that you seem interested in are
unlikely to happen regardless of the syntax changes SE-0066 imply, and
SE-0066 doesn’t have anything to do with that.

It is most disappointing to read these sorts of statements.

One of the things that I have noticed over the last year or so of working
with Swift is a trend in the community of libriaries being written for
Swift towards some of these "system semantics" (i.e., functional paradigms)
like applicatives and such.

Granted I may have a selection bias towards these sorts of libraries.
That is, I tried one library that did some of this stuff so then I tried
more. Eventually stumbling into an enclave of functional practioners of
Swift. I'm willing to admit that I have not conducted a scientific survey.

But from my vantage we have a minority of Swift users participating in
these evolution discussions. Albeit, judging from the e-mail volume, an
extremely _vocal_ minority. I worry that these things become an echo
chamber and those not involved will look at some of the "writing on the
wall" and think differently about Swift going forward. Indeed for those
people they may look at Swift 3 and say "I did not leave Swift; Swift left
me."

What is more is that those not participating in these discussions now may
leave them with no recourse to be heard. Because apparently Swift 3 is a
do-or-die release (or as the author of this evolution put it: "It is now or
never."). I wonder what portion of Swift developers, the ones who want to
see Swift be their go-to language for the forseable future, understand the
implications or justifications for a Swift 3 release.

All that having been said, I get it, decisions are made by those who show
up. Roger that. I also understand and agree with the desire to make Swift
its own language. To show restraint at the urge to turn the language into a
hodge podge of the "greatest hits" of language paradigms. I sincerely
appreciate the difficulty of the task for the Swift core team.

I realized at the end that I do not really have a point. Apparently I'm
feeling philosphical this Wednesday morning.

What I’m trying to say is that there are a lot of reasons that the Swift type system works the way it does (e.g. inout has very specific behavior that doesn’t work when partially applied, we have specific promotion rules that apply only in argument lists etc). These reasons and features are certainly debatable, but have nothing to do with SE-0066, therefore they seem out of scope for a discussion of SE-0066 to go into.

I agree, but although the model of small changes with immediate benefit has advantages, I think "the big picture" is to important to be ignored.
I don't think this is the case, but those of us whose only source of information is this list have a viewpoint that is narrow compared to a member of the core team (that's just natural — publishing every conversation isn't practical).

Coming back to the topic, there must have been a reason to start with a model where all functions take a single parameter (which might be a tuple), and there must be a good reason to dissociate from that principle.
I think actually knowing those motivations would be beneficial for the evolution process:
Although it's discouraged to discuss proposals with ground shaking consequences here on the list, sharing more of the long-term vision for Swift could help focusing on topics that fit into that vision.

(of course, I might just be missing an important post here or in the Swift blog, so please be patient with me if this is the case)

Best regards,
Tino

Hey,

I'm inserting these opinions into almost every FP discussion, for which I'm sorry, but I believe it's important to remind everyone that there's the rest of us who will run away from Swift if it becomes too FP-y.

One of the things that I have noticed over the last year or so of working with Swift is a trend in the community of libriaries being written for Swift towards some of these "system semantics" (i.e., functional paradigms) like applicatives and such.

Just as an example of a different selection bias, I saw a couple of those, digged in for a little bit and then ran far, far away. I haven't seen any FP-related Swift libraries after that.

I absolutely don't have an impression that Swift has any affinity towards being functional. To me, it embraces mutability and higher-level object design aspects (like protocols) while taking only the bits of FP that are actually useful (e.g. collection methods).

I don't have any data, but I can bet that most software developers on iOS and Mac platforms welcome that, and don't really want the move towards FP.

A.

What do you think of this message by Chris Lattner: [swift-evolution] [Review] SE-0066: Standardize function type argument syntax to require parentheses?

Gwendal

Support your opinion on 100%. IMO Swift is language that has *elements* of FP that help us to build our software, but it was not born to be Pure FP language like Haskel Purely functional - Wikipedia
And I believe will never be, as then we should implement Haskell's I/O system in Swift and other 'features'.

Do we need Haskel instead of Swift? I don't believe so.

···

On 28.04.2016 16:48, Andrey Tarantsov via swift-evolution wrote:

Hey,

I'm inserting these opinions into almost every FP discussion, for which
I'm sorry, but I believe it's important to remind everyone that there's
the rest of us who will run away from Swift if it becomes too FP-y.

One of the things that I have noticed over the last year or so of
working with Swift is a trend in the community of libriaries being
written for Swift towards some of these "system semantics" (i.e.,
functional paradigms) like applicatives and such.

Just as an example of a different selection bias, I saw a couple of
those, digged in for a little bit and then ran far, far away. I haven't
seen any FP-related Swift libraries after that.

I absolutely don't have an impression that Swift has any affinity
towards being functional. To me, it embraces mutability and higher-level
object design aspects (like protocols) while taking only the bits of FP
that are actually useful (e.g. collection methods).

I don't have any data, but I can bet that most software developers on
iOS and Mac platforms welcome that, and don't really want the move
towards FP.

A.

_______________________________________________ swift-evolution mailing
list swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution