On Apr 26, 2016, at 3:37 PM, Mishal Awadah <[email protected]> wrote:
> 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
>
> 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
>
>
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution