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

Reply via email to