Re: [swift-evolution] [Proposal] Typed throws

2017-02-22 Thread Anton Zhilin via swift-evolution
As a follow-up, here is code that you can test now. It demonstrates the
same, but with normal function result.

func createArbitrary(usingGenerator f: () -> (T)) -> T {
let any: Any = 42 as Any
if Int.self is T.Type {
let t = any as! T
return t
}
return f()
}
print(createArbitrary(usingGenerator: { return 5 }))  //=> 42

And yes, nobody should do these tricks in production code :P

2017-02-22 21:15 GMT+03:00 Anton Zhilin :

I understand how parametric polymorphism works *in Haskell*. But we talk
> about Swift, and there *is* a way to get an instance of E. I’ll explain
> it another way:
>
> func bypassRethrows(_ f: () throws(E) -> ()) throws(E) {
> let error: Error = MyError()  // create an instance of `MyError`
> if MyError.self is E.Type {   // in case `E` happens to be `MyError`
> let e: E = error as! E// then we've actually created an instance 
> of `E`, and we can downcast safely
> throw e   // voila, acquired an instance of `E`
> }
> }
> let f: () throws MyError -> () = { }
> try bypassRethrows(f) // actually throws `MyError`, without ever 
> calling `f`
>
> What line here seems impossible?
>
​
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Typed throws

2017-02-22 Thread Anton Zhilin via swift-evolution
I understand how parametric polymorphism works *in Haskell*. But we talk
about Swift, and there *is* a way to get an instance of E. I’ll explain it
another way:

func bypassRethrows(_ f: () throws(E) -> ()) throws(E) {
let error: Error = MyError()  // create an instance of `MyError`
if MyError.self is E.Type {   // in case `E` happens to be `MyError`
let e: E = error as! E// then we've actually created an
instance of `E`, and we can downcast safely
throw e   // voila, acquired an instance of `E`
}
}
let f: () throws MyError -> () = { }
try bypassRethrows(f) // actually throws `MyError`,
without ever calling `f`

What line here seems impossible?

2017-02-22 18:39 GMT+03:00 Matthew Johnson :

No because there are many types that conform to `Error` but are not `E` and
> the signature says you only throw `E`.  You have no way to get an instance
> of `E` except by catching one thrown by `f` because `Error` does not have
> any initializers and you don’t have any visibility to anything that
> provides an `E` in any way except when `f` throws.
>
> I am hoping to have time to write up my analysis of generic rethrowing
> functions later today.  There are some very interesting tradeoffs we need
> to make.
>
​
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Typed throws

2017-02-22 Thread Matthew Johnson via swift-evolution

> On Feb 22, 2017, at 7:10 AM, Anton Zhilin  wrote:
> 
> How about this:
> 
> func bypassRethrows(_ f: () throws(E) -> ()) throws(E) {
> if let e = (MyError() as Error) as? E {
> throw e
> }
> }
> I obviously can’t “test” this right now, but should work?
> 
> 

No because there are many types that conform to `Error` but are not `E` and the 
signature says you only throw `E`.  You have no way to get an instance of `E` 
except by catching one thrown by `f` because `Error` does not have any 
initializers and you don’t have any visibility to anything that provides an `E` 
in any way except when `f` throws.

I am hoping to have time to write up my analysis of generic rethrowing 
functions later today.  There are some very interesting tradeoffs we need to 
make.

> 2017-02-22 3:42 GMT+03:00 Colin Barrett  >:
> 
> 
> 
> On Sun, Feb 19, 2017 at 2:34 PM Anton Zhilin via swift-evolution 
> > wrote:
> Now that I think about it, generic throws does not exactly cover rethrows.
> Firstly, rethrows has semantic information that function itself does not 
> throw—it would be lost.
> 
> That's not true. Parametric polymorphism guarantees that rethrows and 
> polymorphic throw are the same. 
> 
> For example, you can prove that as a consequence of parametricity that there 
> is only one (pure) function in the of the set of all functions with the type 
> ``forall A. A -> A'' and furthermore that it is the identity function.
> 
> The intuition behind this is that you (meaning the fiction; imagine being a 
> function!) cannot construct your own value of "A" since you don't have any 
> information about what "A" is. The only place to get an "A" is from your 
> argument.
> 
> 

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


Re: [swift-evolution] [Proposal] Typed throws

2017-02-22 Thread Anton Zhilin via swift-evolution
How about this:

func bypassRethrows(_ f: () throws(E) -> ()) throws(E) {
if let e = (MyError() as Error) as? E {
throw e
}
}

I obviously can’t “test” this right now, but should work?

2017-02-22 3:42 GMT+03:00 Colin Barrett :

On Sun, Feb 19, 2017 at 2:34 PM Anton Zhilin via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> Now that I think about it, generic throws does not exactly cover rethrows
>> .
>> Firstly, rethrows has semantic information that function itself does not
>> throw—it would be lost.
>>
> That's not true. Parametric polymorphism guarantees that rethrows and
> polymorphic throw are the same.
>
> For example, you can prove that as a consequence of parametricity that
> there is only one (pure) function in the of the set of all functions with
> the type ``forall A. A -> A'' and furthermore that it is the identity
> function.
>
> The intuition behind this is that you (meaning the fiction; imagine being
> a function!) cannot construct your own value of "A" since you don't have
> any information about what "A" is. The only place to get an "A" is from
> your argument.
>
​
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Typed throws

2017-02-21 Thread Colin Barrett via swift-evolution
On Sun, Feb 19, 2017 at 2:34 PM Anton Zhilin via swift-evolution <
swift-evolution@swift.org> wrote:

> Now that I think about it, generic throws does not exactly cover rethrows.
> Firstly, rethrows has semantic information that function itself does not
> throw—it would be lost.
>

That's not true. Parametric polymorphism guarantees that rethrows and
polymorphic throw are the same.

For example, you can prove that as a consequence of parametricity that
there is only one (pure) function in the of the set of all functions with
the type ``forall A. A -> A'' and furthermore that it is the identity
function.

The intuition behind this is that you (meaning the fiction; imagine being a
function!) cannot construct your own value of "A" since you don't have any
information about what "A" is. The only place to get an "A" is from your
argument.

Secondly, rethrows allows a function with multiple throwing function
> parameters to become non-throwing iff all the arguments are non-throwing.
> How would you express it with generics?
> In the proposal, in this case you are required to provide a non-generic
> supertype of all used error types. This type can’t just turn into Never
> automatically.
>
> One solution would be to retain rethrows as an additional attribute.
> It would help with semantic information, and resulting error will be able
> to turn into Never as a special case—now that we know, that this function
> doesn’t throw that error itself.
>
> 2017-02-19 0:16 GMT+03:00 Martin Waitz :
>
>
> Am 18.02.2017 um 17:37 schrieb Matthew Johnson via swift-evolution <
> swift-evolution@swift.org>:
>
> Thank you for taking the time to put this proposal together Anton!  I
> really want to see typed throws make it into Swift 4.  This will be a very
> nice feature to have.
>
> I noticed that you included Joe Groff’s idea of replacing `rethrows` by
> making every function have an error type which is by default `Never` for
> non-throwing functions and `Error` for throwing functions that do not
> specify an error type.
>
> I want to urge you to consider updating the proposal to take this
> direction now rather than later.  This is a breaking change which means the
> longer we wait the harder it is to justify.  In fact, I think incorporating
> the breaking change could increase the chances of it being accepted for
> Swift 4.  Without that it is a purely additive change and those are not
> being given priority in the Swift 4 release.
>
>
> Seconded.
> With typed throwing function parameters, it makes a lot of sense to be
> able to specify the rethrown type, based on the function given as parameter.
>
> ​
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Typed throws

2017-02-21 Thread Matthew Johnson via swift-evolution


Sent from my iPhone

> On Feb 20, 2017, at 5:51 PM, Anton Zhilin  wrote:
> 
> 2017-02-21 1:21 GMT+03:00 Matthew Johnson :
>> 
>> Thanks for the links.  I scanned through them somewhat quickly and didn’t 
>> see anything that specifically said `Never` should conform to all protocols. 
>>  Did you see that specifically?  I only saw mentions of it being a bottom 
>> type and therefore a subtype of all types, which I think is a bit different.
>> 
>> I think a big part of the confusion here revolves around the distinction 
>> between a type `T` being a subtype of another type `U` and `Type` being a 
>> subtype of `Type` (using the syntax in your metatype refactoring 
>> proposal).  I’m not an expert in this area, but I suspect that `Never` can 
>> be a subtype of all existential types but without requiring it to actually 
>> *conform* to all protocols.  Any non-instance protocol requirements are not 
>> available on existentials (afaik).
>  
> I didn't fully understand about metatypes, but otherwise yes indeed.
> 
>> Yes, I understood the example and it’s a good one.  What I’m wondering is 
>> what benefit you actually get from this.  There are two places where this 
>> default initializer could be used:
>> 
>> 1. In `seq` itself.  But it seems highly dubious to throw an error you know 
>> nothing about.  Why does `seq` need the ability to construct an error of the 
>> same type as a function given to it without knowing anything more about that 
>> error type.  Is there a use case for this?
>> 2. In callers of `seq`.  Why would the caller care if the error type that 
>> `seq` can throw has a default initializer?  Is there a use case for this?
>> 
>> In other words, why do you want to specify that the type of error that might 
>> be thrown must have a default initializer?  I can’t think of any possible 
>> circumstance where this would be valuable.
>> 
>> The same question can be asked of any other static requirements.  What are 
>> the use cases?  These seem highly theoretical to me.  Maybe I’m missing 
>> something, but if so I would like to see an example of how it is *used*, not 
>> just how you would need to write an extra overload without `rethrows`.
> 
> Seems highly theoretical to me as well.
> 
>> There is a potentially more practical benefit of keeping rethrows.  If a 
>> function is declared with `rethrows` we know that the function itself does 
>> not throw.  It only throws if one of its arguments throw when it invokes 
>> them.  This is a subtle but important difference.  For example, users 
>> calling a rethrowing function know that *they* have control over whether or 
>> not the call *actually* throws.  The caller might pass a couple of functions 
>> that *can* throw but in this particular case are known not to throw.  That 
>> could influence how the caller handles errors in the surrounding scope.
> 
> Agreed. Now I lean towards leaving the proposal as is.

I've been continuing to think through these generic rethrowing functions and 
have identified a problem I think we want to address before submitting a 
proposal for review.  Please hold off until I have a chance to write a post 
describing the problem and laying out our options.

> 
> 2017-02-21 1:21 GMT+03:00 Matthew Johnson :
>> 
>>> On Feb 20, 2017, at 11:14 AM, Anton Zhilin  wrote:
>>> 
>>> 2017-02-20 18:23 GMT+03:00 Matthew Johnson :
>>> 
>>> 
>>> 
 
> On Feb 20, 2017, at 3:58 AM, Anton Zhilin  wrote:
> But that raises another concern. In a previous discussion, it was taken 
> for granted that Never should conform to all protocols
> 
 
 Do you have a pointer to this discussion?  I must have missed it.
>>> 
>>> 
>>> Here is the discussion where the idea of “empty” type originated.
>>> Some messages on the topic ended up being there.
>>> 
>>> This is the earliest mention of usage of this empty type for rethrows I 
>>> could find.
>>> Some related messages are here as well.
>>> 
>>> 
>>> We called this type NoReturn and meant it to be the bottom type, i.e. 
>>> subtype of all types, meaning that if you have an instance of 
>>> NoReturn—which can only happen in unreachable sections of code—then you can 
>>> convert it to any type. It should have worked like this:
>>> 
>>> func fatalError() -> Never
>>> 
>>> func divide(a: Int, b: Int) -> Int {
>>> if b == 0 {
>>> let n: Never = fatalError()
>>> return n as Int
>>> }
>>> return a / b
>>> }
>>> I pushed the idea of replacing rethrows with Never, inspired by Haskell. 
>>> Although Haskell doesn’t have static function requirements and initializer 
>>> requirements.
>>> 
>>> 
>> 
>> Thanks for the links.  I scanned through them somewhat quickly and didn’t 
>> see anything that specifically said `Never` should conform to all protocols. 
>>  Did you see that specifically?  I only saw mentions of it 

Re: [swift-evolution] [Proposal] Typed throws

2017-02-20 Thread Anton Zhilin via swift-evolution
2017-02-21 1:21 GMT+03:00 Matthew Johnson :
>
> Thanks for the links.  I scanned through them somewhat quickly and didn’t
> see anything that specifically said `Never` should conform to all
> protocols.  Did you see that specifically?  I only saw mentions of it being
> a bottom type and therefore a subtype of all types, which I think is a bit
> different.
>
> I think a big part of the confusion here revolves around the distinction
> between a type `T` being a subtype of another type `U` and `Type` being
> a subtype of `Type` (using the syntax in your metatype refactoring
> proposal).  I’m not an expert in this area, but I suspect that `Never` can
> be a subtype of all existential types but without requiring it to actually
> *conform* to all protocols.  Any non-instance protocol requirements are not
> available on existentials (afaik).
>

I didn't fully understand about metatypes, but otherwise yes indeed.

Yes, I understood the example and it’s a good one.  What I’m wondering is
> what benefit you actually get from this.  There are two places where this
> default initializer could be used:
>
> 1. In `seq` itself.  But it seems highly dubious to throw an error you
> know nothing about.  Why does `seq` need the ability to construct an error
> of the same type as a function given to it without knowing anything more
> about that error type.  Is there a use case for this?
> 2. In callers of `seq`.  Why would the caller care if the error type that
> `seq` can throw has a default initializer?  Is there a use case for this?
>
> In other words, why do you want to specify that the type of error that
> might be thrown must have a default initializer?  I can’t think of any
> possible circumstance where this would be valuable.
>
> The same question can be asked of any other static requirements.  What are
> the use cases?  These seem highly theoretical to me.  Maybe I’m missing
> something, but if so I would like to see an example of how it is *used*,
> not just how you would need to write an extra overload without `rethrows`.
>

Seems highly theoretical to me as well.

There is a potentially more practical benefit of keeping rethrows.  If a
> function is declared with `rethrows` we know that the function itself does
> not throw.  It only throws if one of its arguments throw when it invokes
> them.  This is a subtle but important difference.  For example, users
> calling a rethrowing function know that *they* have control over whether or
> not the call *actually* throws.  The caller might pass a couple of
> functions that *can* throw but in this particular case are known not to
> throw.  That could influence how the caller handles errors in the
> surrounding scope.
>

Agreed. Now I lean towards leaving the proposal as is.

2017-02-21 1:21 GMT+03:00 Matthew Johnson :

>
> On Feb 20, 2017, at 11:14 AM, Anton Zhilin  wrote:
>
> 2017-02-20 18:23 GMT+03:00 Matthew Johnson :
>
>
>
>> On Feb 20, 2017, at 3:58 AM, Anton Zhilin  wrote:
>>
>> But that raises another concern. In a previous discussion, it was taken
>> for granted that Never should conform to all protocols
>>
>> Do you have a pointer to this discussion?  I must have missed it.
>>
>
>
> Here
> 
> is the discussion where the idea of “empty” type originated.
> Some messages on the topic ended up being there
> .
>
> This  is the
> earliest mention of usage of this empty type for rethrows I could find.
> Some related messages are here
> 
> as well.
>
> We called this type NoReturn and meant it to be the *bottom type*, i.e.
> subtype of all types, meaning that if you have an instance of NoReturn—which
> can only happen in unreachable sections of code—then you can convert it to
> any type. It should have worked like this:
>
> func fatalError() -> Never
>
> func divide(a: Int, b: Int) -> Int {
> if b == 0 {
> let n: Never = fatalError()
> return n as Int
> }
> return a / b
> }
>
> I pushed the idea of replacing rethrows with Never, inspired by Haskell.
> Although Haskell doesn’t have static function requirements and initializer
> requirements.
>
>
> Thanks for the links.  I scanned through them somewhat quickly and didn’t
> see anything that specifically said `Never` should conform to all
> protocols.  Did you see that specifically?  I only saw mentions of it being
> a bottom type and therefore a subtype of all types, which I think is a bit
> different.
>
> I think a big part of the confusion here revolves around the distinction
> between a type `T` being a subtype of another type `U` and `Type` being
> a subtype of `Type` (using the 

Re: [swift-evolution] [Proposal] Typed throws

2017-02-20 Thread Matthew Johnson via swift-evolution

> On Feb 20, 2017, at 11:14 AM, Anton Zhilin  wrote:
> 
> 2017-02-20 18:23 GMT+03:00 Matthew Johnson  >:
> 
> 
> 
> 
>> On Feb 20, 2017, at 3:58 AM, Anton Zhilin > > wrote:
>> But that raises another concern. In a previous discussion, it was taken for 
>> granted that Never should conform to all protocols
>> 
> 
> Do you have a pointer to this discussion?  I must have missed it.
> 
> 
> Here 
> 
>  is the discussion where the idea of “empty” type originated.
> Some messages on the topic ended up being there 
> .
> 
> This  is the 
> earliest mention of usage of this empty type for rethrows I could find.
> Some related messages are here 
> 
>  as well.
> 
> 
> We called this type NoReturn and meant it to be the bottom type, i.e. subtype 
> of all types, meaning that if you have an instance of NoReturn—which can only 
> happen in unreachable sections of code—then you can convert it to any type. 
> It should have worked like this:
> 
> func fatalError() -> Never
> 
> func divide(a: Int, b: Int) -> Int {
> if b == 0 {
> let n: Never = fatalError()
> return n as Int
> }
> return a / b
> }
> I pushed the idea of replacing rethrows with Never, inspired by Haskell. 
> Although Haskell doesn’t have static function requirements and initializer 
> requirements.
> 
> 

Thanks for the links.  I scanned through them somewhat quickly and didn’t see 
anything that specifically said `Never` should conform to all protocols.  Did 
you see that specifically?  I only saw mentions of it being a bottom type and 
therefore a subtype of all types, which I think is a bit different.

I think a big part of the confusion here revolves around the distinction 
between a type `T` being a subtype of another type `U` and `Type` being a 
subtype of `Type` (using the syntax in your metatype refactoring proposal).  
I’m not an expert in this area, but I suspect that `Never` can be a subtype of 
all existential types but without requiring it to actually *conform* to all 
protocols.  Any non-instance protocol requirements are not available on 
existentials (afaik).

> 
> 
>> , because if one obtains an instance of Never (and they won’t), then 
>> everything is possible. But now we say that Never can’t conform to Default, 
>> because this would break its very invariant. Also it can’t conform to any 
>> protocol with static members or initializers.
>> 
> 
> It seems highly problematic to me to say that never conforms to any protocol 
> with non-instance requirements.
> 
> 
> Here is an example with instance requirements only:
> 
> protocol MakesPizza {
> func cook() -> Pizza
> }
> extension Never : MakesPizza {
> func cook() -> Pizza {
> // this method will never be called anyway
> burnThisComputer()
> }
> }
> 
> let maestroLaPizza = isHeAtWork ? validMaestro : (fatalError("something went 
> wrong") as MakesPizza)
> maestroLaPizza.cook()
> In this way, Never can conform to any protocol with only instance 
> requirements.
> 
Sure.

> 
> 
>> But then basically, Never trick can’t be used when we request anything more 
>> than Error from generic error type (with static members or initializers). So 
>> this approach turns out to be more limiting than rethrows.
>> 
> 
> Can you elaborate here?  If you require a function to throw an error type 
> that has non-instance requirements then you would necessarily be restricting 
> callers to provide a throwing function.  It is not possible to express such a 
> function with `rethrows`.  You can’t talk about the error type at all.  If 
> you could talk about the error type and were able to constrain it in this way 
> `rethrows` would necessarily have to exhibit the same behavior as the generic 
> version.  The behavior arises out of the constraint you are applying, not the 
> mechanism by which you forward the type.
> 
> 
> With rethrows approach:
> 
> protocol BaseError : Error {
> init()
> }
> 
> func seq(f: () throws(E1) -> (), g: () throws(E2) -> ()) 
> rethrows(BaseError)
>  where E1: BaseError, E2: BaseError { ... }
> With Never approach, we have to create two separate functions for the same 
> effect, because Never does not fit in BaseError:
> 
> func seq(f: () throws(E1) -> (), g: () throws(E2) -> ()) 
> throws(BaseError)
>  where E1: BaseError, E2: BaseError {
> // It never actually throws E1() or E2() itself, but this fact can't be 
> reflected in the signature
> }
> 
> func seq(f: () -> (), g: () -> ()) {
> // repeat the body
> }
> That’s where loss of information (which I 

Re: [swift-evolution] [Proposal] Typed throws

2017-02-20 Thread Anton Zhilin via swift-evolution
I messed up with links a little bit, duplicating one of them. Here

is another one.
​
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Typed throws

2017-02-20 Thread Anton Zhilin via swift-evolution
2017-02-20 18:23 GMT+03:00 Matthew Johnson :


> On Feb 20, 2017, at 3:58 AM, Anton Zhilin  wrote:
>
> But that raises another concern. In a previous discussion, it was taken
> for granted that Never should conform to all protocols
>
> Do you have a pointer to this discussion?  I must have missed it.
>
Here

is the discussion where the idea of “empty” type originated.
Some messages on the topic ended up being there
.

This  is the
earliest mention of usage of this empty type for rethrows I could find.
Some related messages are here

as well.

We called this type NoReturn and meant it to be the *bottom type*, i.e.
subtype of all types, meaning that if you have an instance of NoReturn—which
can only happen in unreachable sections of code—then you can convert it to
any type. It should have worked like this:

func fatalError() -> Never

func divide(a: Int, b: Int) -> Int {
if b == 0 {
let n: Never = fatalError()
return n as Int
}
return a / b
}

I pushed the idea of replacing rethrows with Never, inspired by Haskell.
Although Haskell doesn’t have static function requirements and initializer
requirements.

, because if one obtains an instance of Never (and they won’t), then
> everything is possible. But now we say that Never can’t conform to Default,
> because this would break its very invariant. Also it can’t conform to any
> protocol with static members or initializers.
>
> It seems highly problematic to me to say that never conforms to any
> protocol with non-instance requirements.
>
Here is an example with instance requirements only:

protocol MakesPizza {
func cook() -> Pizza
}
extension Never : MakesPizza {
func cook() -> Pizza {
// this method will never be called anyway
burnThisComputer()
}
}

let maestroLaPizza = isHeAtWork ? validMaestro :
(fatalError("something went wrong") as MakesPizza)
maestroLaPizza.cook()

In this way, Never can conform to any protocol with only instance
requirements.

But then basically, Never trick can’t be used when we request anything more
> than Error from generic error type (with static members or initializers).
> So this approach turns out to be more limiting than rethrows.
>
> Can you elaborate here?  If you require a function to throw an error type
> that has non-instance requirements then you would necessarily be
> restricting callers to provide a throwing function.  It is not possible to
> express such a function with `rethrows`.  You can’t talk about the error
> type at all.  If you could talk about the error type and were able to
> constrain it in this way `rethrows` would necessarily have to exhibit the
> same behavior as the generic version.  The behavior arises out of the
> constraint you are applying, not the mechanism by which you forward the
> type.
>
With rethrows approach:

protocol BaseError : Error {
init()
}

func seq(f: () throws(E1) -> (), g: () throws(E2) -> ())
rethrows(BaseError)
 where E1: BaseError, E2: BaseError { ... }

With Never approach, we have to create two separate functions for the same
effect, because Never does not fit in BaseError:

func seq(f: () throws(E1) -> (), g: () throws(E2) -> ())
throws(BaseError)
 where E1: BaseError, E2: BaseError {
// It never actually throws E1() or E2() itself, but this fact
can't be reflected in the signature
}

func seq(f: () -> (), g: () -> ()) {
// repeat the body
}

That’s where loss of information (which I meantioned earlier) hurts: we
can’t apply magic and say “if E1 and E2 are Never then seq does not throw.
Because it *can* throw anyway.

Well, I’m just repeating myself, at least I gave a bit more complete
example :)
​
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Typed throws

2017-02-20 Thread Anton Zhilin via swift-evolution
2017-02-19 23:29 GMT+03:00 Matthew Johnson :

Thanks.  There is nothing wrong with this at all.  Your second `exec` would
> not accept a non-throwing function because `Never` cannot conform to
> `Default`.  If it didn’t include the `Default` constraint it would not be
> able to `throw E()`.
>
But that raises another concern. In a previous discussion, it was taken for
granted that Never should conform to all protocols, because if one obtains
an instance of Never (and they won’t), then everything is possible. But now
we say that Never can’t conform to Default, because this would break its
very invariant. Also it can’t conform to any protocol with static members
or initializers.

But then basically, Never trick can’t be used when we request anything more
than Error from generic error type (with static members or initializers).
So this approach turns out to be more limiting than rethrows.
Don’t misunderstand me—I love the idea of Never replacing rethrows. Just
want to make sure we don’t lose anything important by the way.

If you remove the `Default` constraint and change `throws(E)` to `throws`,
> and throw `MyError()` in place of `E()` in both places then it behaves
> exactly as the first example. We don’t lose any expressivity at all.
>
> This is actually an example of a strength of Joe’s suggestion: the second
> `exec` is able to throw an error of a type that matches the error that
> might be thrown by the calling argument `f`.  I’m not sure of where this
> might be useful but it is definitely not possible with `rethrows` while it
> is possible with Joe’s proposal.  We have more flexibility in API design
> under Joe’s proposal.
>
Nice. Whether we can throw the error ourselves depends on our ability to
create the error.

You did make a great point about coalescing error types from several
> different function arguments.  That’s an edge case, but the inability to
> coalesce is indeed a problem that probably needs to be addressed by the
> typed throws proposal in one way or another (if we don’t go with Joe’s
> suggestion we would need to specify how `rethrows` behaves in cases like
> this in some detail).
>
​
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Typed throws

2017-02-19 Thread Matthew Johnson via swift-evolution

> On Feb 19, 2017, at 2:16 PM, Anton Zhilin  wrote:
> 
> 2017-02-19 22:59 GMT+03:00 Matthew Johnson  >:
> 
> 
> 
>> On Feb 19, 2017, at 1:32 PM, Anton Zhilin > > wrote:
>> 
>> Now that I think about it, generic throws does not exactly cover rethrows.
>> Firstly, rethrows has semantic information that function itself does not 
>> throw—it would be lost.
>> 
> Can you elaborate further on what you mean by this?
> 
> 
> protocol Default { init() }
> 
> func exec(f: () throws -> Void) rethrows
> {
> try f()
> throw MyError()  // error because of rethrows
> }
> 
> func exec(f: () throws(E) -> Void) throws(E)
>  where E: Error & Default
> {
> try f()
> throw E()  // okay
> }

Thanks.  There is nothing wrong with this at all.  Your second `exec` would not 
accept a non-throwing function because `Never` cannot conform to `Default`.  If 
it didn’t include the `Default` constraint it would not be able to `throw E()`. 
 

If you remove the `Default` constraint and change `throws(E)` to `throws`, and 
throw `MyError()` in place of `E()` in both places then it behaves exactly as 
the first example. We don’t lose any expressivity at all.

This is actually an example of a strength of Joe’s suggestion: the second 
`exec` is able to throw an error of a type that matches the error that might be 
thrown by the calling argument `f`.  I’m not sure of where this might be useful 
but it is definitely not possible with `rethrows` while it is possible with 
Joe’s proposal.  We have more flexibility in API design under Joe’s proposal.

You did make a great point about coalescing error types from several different 
function arguments.  That’s an edge case, but the inability to coalesce is 
indeed a problem that probably needs to be addressed by the typed throws 
proposal in one way or another (if we don’t go with Joe’s suggestion we would 
need to specify how `rethrows` behaves in cases like this in some detail).


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


Re: [swift-evolution] [Proposal] Typed throws

2017-02-19 Thread Anton Zhilin via swift-evolution
2017-02-19 22:59 GMT+03:00 Matthew Johnson :

On Feb 19, 2017, at 1:32 PM, Anton Zhilin  wrote:
>
> Now that I think about it, generic throws does not exactly cover rethrows.
> Firstly, rethrows has semantic information that function itself does not
> throw—it would be lost.
>
> Can you elaborate further on what you mean by this?
>
protocol Default { init() }

func exec(f: () throws -> Void) rethrows
{
try f()
throw MyError()  // error because of rethrows
}

func exec(f: () throws(E) -> Void) throws(E)
 where E: Error & Default
{
try f()
throw E()  // okay
}

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


Re: [swift-evolution] [Proposal] Typed throws

2017-02-19 Thread Matthew Johnson via swift-evolution

> On Feb 19, 2017, at 1:32 PM, Anton Zhilin  wrote:
> 
> Now that I think about it, generic throws does not exactly cover rethrows.
> Firstly, rethrows has semantic information that function itself does not 
> throw—it would be lost.
> 
Can you elaborate further on what you mean by this?

> Secondly, rethrows allows a function with multiple throwing function 
> parameters to become non-throwing iff all the arguments are non-throwing.
> How would you express it with generics?
> In the proposal, in this case you are required to provide a non-generic 
> supertype of all used error types. This type can’t just turn into Never 
> automatically.
> 
This is a very good question.  I’m curious if Joe has a solution that doesn’t 
require introducing any additional features into Swift.

The answer I would like to see (that won’t happen in Swift 4) is to adopt some 
of the ideas in my value subtyping manifesto, including structural unions (that 
*do not* expose any members, even if there are members that all types have in 
common).  All you would be able to do with such a union is convert from one of 
its constituent types to the union type and cast back down to one of the 
constituent types.

Having unions like that would very elegantly solve the problem of a function 
that needs to throw more than one type.  It also covers the case you bring up: 
`Never | Never | Never` would be the exact same type as `Never`.  You would 
never write out `Never | Never | Never` of course, but in a generic context 
it’s important that we be able to spell it that way and have it collapse to a 
simple unordered set of its constituent types.

Use of these structural union types would be discouraged in most cases, but 
they would be very powerful and useful in specialized contexts.  Error handling 
is one of those contexts.  Another is at the boundary of a system when you need 
to accept a heterogenous collection of a small, fixed set of types (as is 
discussed in the thread about open and public protocols).

> One solution would be to retain rethrows as an additional attribute.
> It would help with semantic information, and resulting error will be able to 
> turn into Never as a special case—now that we know, that this function 
> doesn’t throw that error itself.
> 
I'm curious to hear Joe’s thought on this.  It’s possible this would be a 
necessary bridge solution until we have something more permanent as I described 
above.

> 2017-02-19 0:16 GMT+03:00 Martin Waitz  >:
> 
> 
> 
> 
>> Am 18.02.2017 um 17:37 schrieb Matthew Johnson via swift-evolution 
>> >:
>> 
>> Thank you for taking the time to put this proposal together Anton!  I really 
>> want to see typed throws make it into Swift 4.  This will be a very nice 
>> feature to have.
>> 
>> I noticed that you included Joe Groff’s idea of replacing `rethrows` by 
>> making every function have an error type which is by default `Never` for 
>> non-throwing functions and `Error` for throwing functions that do not 
>> specify an error type.  
>> 
>> I want to urge you to consider updating the proposal to take this direction 
>> now rather than later.  This is a breaking change which means the longer we 
>> wait the harder it is to justify.  In fact, I think incorporating the 
>> breaking change could increase the chances of it being accepted for Swift 4. 
>>  Without that it is a purely additive change and those are not being given 
>> priority in the Swift 4 release.
> 
> Seconded.
> With typed throwing function parameters, it makes a lot of sense to be able 
> to specify the rethrown type, based on the function given as parameter.
> 
> 

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


Re: [swift-evolution] [Proposal] Typed throws

2017-02-19 Thread Anton Zhilin via swift-evolution
2017-02-19 0:16 GMT+03:00 Martin Waitz :
>
> Now some bike-shedding:
> I’m not really happy with the `throws(Type)` syntax, as it is too close to
> function parameters.
> Why exactly is `throws Type` ambiguous?
> The proposal mentions `Type -> Result` as potential thrown type, but
> functions cannot conform to `Error`.
>

Well, it's expected to change with one of the follow-up proposals.


> Maybe we can instruct the parser to just allow simple type names between
> `throws` and the arrow `->`.
>

The ambiguity here is not so "to compiler" as "to human". We don't want
people to spend extra time parsing the declaration.

If that is not possible, we should at least try to find some visual hints
> to separate Error type from function parameters.
>
> E.g. we could use brackets (think of: we are specialising the `throws`):
>
> func foo() throws { … }
>

 I personally prefer parentheses, because there is precedence of
parametrized attributes. I wonder what others think on angle brackets
option.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Typed throws

2017-02-19 Thread Anton Zhilin via swift-evolution
Now that I think about it, generic throws does not exactly cover rethrows.
Firstly, rethrows has semantic information that function itself does not
throw—it would be lost.

Secondly, rethrows allows a function with multiple throwing function
parameters to become non-throwing iff all the arguments are non-throwing.
How would you express it with generics?
In the proposal, in this case you are required to provide a non-generic
supertype of all used error types. This type can’t just turn into Never
automatically.

One solution would be to retain rethrows as an additional attribute.
It would help with semantic information, and resulting error will be able
to turn into Never as a special case—now that we know, that this function
doesn’t throw that error itself.

2017-02-19 0:16 GMT+03:00 Martin Waitz :


> Am 18.02.2017 um 17:37 schrieb Matthew Johnson via swift-evolution <
> swift-evolution@swift.org>:
>
> Thank you for taking the time to put this proposal together Anton!  I
> really want to see typed throws make it into Swift 4.  This will be a very
> nice feature to have.
>
> I noticed that you included Joe Groff’s idea of replacing `rethrows` by
> making every function have an error type which is by default `Never` for
> non-throwing functions and `Error` for throwing functions that do not
> specify an error type.
>
> I want to urge you to consider updating the proposal to take this
> direction now rather than later.  This is a breaking change which means the
> longer we wait the harder it is to justify.  In fact, I think incorporating
> the breaking change could increase the chances of it being accepted for
> Swift 4.  Without that it is a purely additive change and those are not
> being given priority in the Swift 4 release.
>
>
> Seconded.
> With typed throwing function parameters, it makes a lot of sense to be
> able to specify the rethrown type, based on the function given as parameter.
>
​
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Typed throws

2017-02-18 Thread Martin Waitz via swift-evolution

> Am 18.02.2017 um 17:37 schrieb Matthew Johnson via swift-evolution 
> :
> 
> Thank you for taking the time to put this proposal together Anton!  I really 
> want to see typed throws make it into Swift 4.  This will be a very nice 
> feature to have.
> 
> I noticed that you included Joe Groff’s idea of replacing `rethrows` by 
> making every function have an error type which is by default `Never` for 
> non-throwing functions and `Error` for throwing functions that do not specify 
> an error type.  
> 
> I want to urge you to consider updating the proposal to take this direction 
> now rather than later.  This is a breaking change which means the longer we 
> wait the harder it is to justify.  In fact, I think incorporating the 
> breaking change could increase the chances of it being accepted for Swift 4.  
> Without that it is a purely additive change and those are not being given 
> priority in the Swift 4 release.

Seconded.
With typed throwing function parameters, it makes a lot of sense to be able to 
specify the rethrown type, based on the function given as parameter.

Now some bike-shedding:
I’m not really happy with the `throws(Type)` syntax, as it is too close to 
function parameters.
Why exactly is `throws Type` ambiguous?
The proposal mentions `Type -> Result` as potential thrown type, but functions 
cannot conform to `Error`.
Maybe we can instruct the parser to just allow simple type names between 
`throws` and the arrow `->`.

If that is not possible, we should at least try to find some visual hints to 
separate Error type from function parameters.

E.g. we could use brackets (think of: we are specialising the `throws`):

func foo() throws { … }

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


Re: [swift-evolution] [Proposal] Typed throws

2017-02-18 Thread Matthew Johnson via swift-evolution
Thank you for taking the time to put this proposal together Anton!  I really 
want to see typed throws make it into Swift 4.  This will be a very nice 
feature to have.

I noticed that you included Joe Groff’s idea of replacing `rethrows` by making 
every function have an error type which is by default `Never` for non-throwing 
functions and `Error` for throwing functions that do not specify an error type. 
 

I want to urge you to consider updating the proposal to take this direction now 
rather than later.  This is a breaking change which means the longer we wait 
the harder it is to justify.  In fact, I think incorporating the breaking 
change could increase the chances of it being accepted for Swift 4.  Without 
that it is a purely additive change and those are not being given priority in 
the Swift 4 release.


> On Feb 18, 2017, at 6:54 AM, Anton Zhilin via swift-evolution 
>  wrote:
> 
> I’ve created a proposal draft, copy-pasting some parts from David Owens’ 
> proposal.
> Here it is .
> 
> I had to make one addition, which hasn’t been discussed yet. Look at Multiple 
> throwing calls 
> 
>  section. Is this feature controversal, or it’s fine to keep in the proposal? 
> Is it feasible from implementation point of view?
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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