> On Mar 15, 2016, at 6:39 AM, Yuta Koshizawa <ko...@koherent.org> wrote: > > 2016-03-15 2:23 GMT+09:00 Joe Groff <jgr...@apple.com>: >> >> Yeah, we extensively discussed adding a Result type internally, but >> ultimately couldn't justify it. The only real use case we could see in the >> wild was for threading errors through CPS-inversion-style abstractions like >> async promises, something we hope to provide proper language support for. >> More generally, expressing effects as monadic values is a pretty awful >> abstraction; aside from polluting the Internet with an endless deluge of >> unhelpful tutorials, they also don't compose cleanly, they impose nesting >> where is desired—you have to pick between Result<Async<T>> and >> Async<Result<T>>, or build ResultT<AsyncT<Identity>><T> out of monad >> transformers—and they don't do the natural thing when used with other >> higher-order abstractions—if you're mapping a `throws` function over a >> collection, you probably want to propagate that error like `rethrows` does, >> not end up with a collection of Result<T>. > > Yes, I know the pain of nested monads and I don't want to encourage > monadic error handling with awful nests. > > To tell the truth, I ultimately desire to unify `Optional`s, `throws` > and `Result`s. > > We have already had `Optional`s which can be used in a monadic way. To > prevent excessive monadic handling, I think we need Automatic > Propagation for `Optional`s. > > ``` > // Automatic Propagation for `Optional`s > let a: Int? = ... > let b: Int? = ... > > do { > let sum: Int = (try a) + (try b) > ... > } catch { // if `a` and/or `b` are `nil` > ... > } > ``` > > Although "Error Handling Rational and Proposal" says `Optional`s > should be used for simple domain errors and are suitable for Manual > Propagation, I think Automatic Propagation is also useful for > `Optional`s. We get `nil` not only as errors but also as empty values. > Our codes are full of `Optional`s. Handling them manually costs a lot. > So I think it is good to have Automatic Propagation for `Optional`s. > > However it is confusing to mix `Optional`s and `throws` functions with > the same keyword `try`. So I think something like `typealias > Optional<T> = Result<T, NilError>`, which could be identical in a > binary form to current `Optional` with `struct NilError: ErrorType > {}`, and unified `throws` and `Result`s would be better. Then we would > have only `Result`s, but it could be used as `Optional`s and `throws`. > > Although `Result`s might make it possible to abuse monadic error > handling, problems of abuses are also true for other language > features: e.g. `(Float, Float)` as `Vector2` instead of `struct > Vector2 { ... }` for tuples. Even if we keep `Optional`s and `throws` > separated, `Optional`s can be handled monadically and we need to > encourage people how and when to use them to prevent abuses. I think > language features cannot prevent abuses, and it is a role of coding > guidelines. > > So I think it is good to unify `Optional`s, `throws` and `Result`s. > But because it seemed too radical, I proposed the part of it at first: > `throws -> Foo` as a syntactic sugar of `-> Result<Foo>`.
I agree, it's nice to be able to open optionals and avoid direct monadic manipulations too. Optionals can be lifted and extracted from a `throws` body fairly easily already, much like a `Result`: enum Nil: ErrorType { case Nil } extension Optional { func getOrThrow() throws -> Wrapped { if let x = self { return x } throw Nil.Nil } } func doOrNil<T, U>(f: (T) throws -> U, x: T) -> U? { do { return try f(x) } catch { return nil } } The latter is provided by the language as `try?` already. If we had typed `throws`, it would be nice to be able to express `throws Nil` more precisely, of course. -Joe > >> I'd rather see us adopt an >> extensible algebraic effects system, something like http://www.eff-lang.org, >> which provides a framework for `throws`, `async` and other control flow >> effects to be cleanly composed and abstracted over. I see `throws` as the >> first seed of that. > > Thank you for the information. Because I am not familiar with Eff, I > will check it. If it composes multiple abstractions well, it must be > great! > > -- Yuta
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution