[swift-evolution] [proposal] Either in the Swift Standard Library

T.J. Usiyan griotspeak at gmail.com
Tue Jan 26 11:36:24 CST 2016


Is there a way that we can capture the desired parts of this proposal in a
Protocol or Protocol-like structure? I'm thinking of some way to specify
behavior that Enums possessing two cases which opt in can share. I
understand that much of it can be done with a protocol now, what stands in
the way of it being worthwhile?

On Tue, Jan 26, 2016 at 12:30 PM, Developer via swift-evolution <
swift-evolution at swift.org> wrote:

> I’m generally with Kevin on this. I’d classify actual-usage of `Either` as
> one of these three:
>
> - often: a rather poorly-named “Result” type (or a slight generalization
> thereof into the “fat optional”, e.g. instead of “X-or-nothing”, it’s
> “X-or-why-not-X?")
>
>
> You've described (T?, U?).  This is not a "fat optional".  And if we must
> use the term, then it's better to think of the reverse: an Optional is a
> thin Either.  It is an Either that offers less information; a lobe of the
> type dedicated to () rather than an actual value.
>
> - occasionally: a rather poorly-named, 2-way sum type (poorly-named b/c
> its convention won’t generalize to 3-way sums, or 4-ways sums, etc.)
>
>
> Good thing Either<Either<...>, Either<...>> works.
>
> - rarely: a use that’s not really either of the above
>
>
> The ErrorT Monad Transformer?
>
> If there are some great uses of `Either` that:
>
> - (a) aren’t just Result/the “fat optional”
>
>
> The Validation type is just that.  I'm going to draw one up and submit it
> to Swiftz.  I'll let you know when that happens.
>
> - (b) aren’t just a 2-way sum
>
>
> I don't understand? Are you literally asking for a non-sum-sum-type?
>
> - (c) support clean-and-*correct* implementations directly in terms of
> standard library functions (e.g., don’t force you to choose between "not
> actually halting iteration” and “re-implementing `reduce` just to get it
> right” )
>
>
> I can fix the example, but perhaps you've mistaken its inclusion in the
> proposal for a call to actually include it in the STL.  It was just a romp
> through the capabilities of the type (see robrix's note about
> Continuation-Passing-isms).
>
> …then this proposal would be a lot stronger for including them.
>
>
> I agree somewhat.  See my notes above.
>
> ~Robert Widmann
>
> 2016/01/26 8:52、plx via swift-evolution <swift-evolution at swift.org>
> のメッセージ:
>
> I’m generally with Kevin on this. I’d classify actual-usage of `Either` as
> one of these three:
>
> - often: a rather poorly-named “Result” type (or a slight generalization
> thereof into the “fat optional”, e.g. instead of “X-or-nothing”, it’s
> “X-or-why-not-X?")
> - occasionally: a rather poorly-named, 2-way sum type (poorly-named b/c
> its convention won’t generalize to 3-way sums, or 4-ways sums, etc.)
> - rarely: a use that’s not really either of the above
>
> …which is why the early discussion veered into discussion of Result and
> structural unions.
>
> Sticking to the topic at hand, I’ll actually pick on the `reduceEarly`
> function in the proposal (as currently-written), because to my eyes that's
> the only example that’s *perhaps* in that third category of interesting
> uses:
>
> - on an infinite sequence it’s not a correct “early exit”; as-written,
> it’s a “never-exit” (defeating the purpose in situation you’d want it to
> actually, you know, exit early)
> - even on a finite sequence, it’ll consume the entire sequence even on an
> “early-exit” (swift sequences are single-pass); this limits its usefulness
> as a building block for other constructs
>
> These defects are, of course, easily fixable by manually writing-out the
> reduce logic; but, if you’re willing to write that out, the implementation
> cost will be about the same for a “direct" solution and the solution using
> `Either`, and given that, it’s not clear that *users* wouldn’t generally
> wind up preferring something like this:
>
> enum IterationDecision {
>   Continue
>   ExitEarly
> }
>
> func reduceEarly<T>(initial: T, combine: (T,Generator.Element) ->
> (T,IterationDecision)) -> T {
>   var result: T = initial
>   for element in self {
>     let (update,decision) = combine(result,element)
>     switch decision {
>       case .Continue: result = update
>       case .EarlyExit: return update
>     }
>   }
>   return result
> }
>
> …where (as a user) the signature and the enumeration make its use
> essentially self-explanatory, versus, say, this:
>
> func reduceEarly<T>(initial: T, combine: (T,Generator.Element) ->
> Either<T,T>) -> T {
>   var result: T = initial
>   for element in self {
>     switch combine(result,element) {
>       case let .Left(update): result = update
>       case let .Right(update): return update
>     }
>   }
>   return result
> }
>
> …where the user will likely have to check the documentation to see which
> of `.Left` and `.Right` means “early-exit” here (unless `Either`’s gone
> sufficiently-pervasive by then that such knowledge will be de rigueur).
>
> If there are some great uses of `Either` that:
>
> - (a) aren’t just Result/the “fat optional”
> - (b) aren’t just a 2-way sum
> - (c) support clean-and-*correct* implementations directly in terms of
> standard library functions (e.g., don’t force you to choose between "not
> actually halting iteration” and “re-implementing `reduce` just to get it
> right” )
>
> …then this proposal would be a lot stronger for including them.
>
> On Jan 26, 2016, at 12:27 AM, Developer via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Are you opposed to the name or the semantics?
>
> I will not accept a revision that reduces the level of abstraction of the
> current proposal.  I will, however, accept name changes.  Result, though, I
> believe is out of the question.  It strongly implies a common but pointed
> set of semantics that discourage thinking of this type as data and more as
> an alternative to throws.  I do not wish to emphasize the error case, or
> the theoretical case, I wish to encourage the general case.  We must
> remember that despite Rust's success, they do not have to live alongside an
> exceptions mechanism like Either does.
>
> ~Robert Widmann
>
> 2016/01/26 0:55、Kevin Ballard via swift-evolution <
> swift-evolution at swift.org> のメッセージ:
>
> There absolutely is a cost. `Result<T>` has a rather intuitive meaning.
> `Either<T>` has *no intuitive meaning whatsoever*. It says absolutely
> *nothing* about what it means beyond the fact that there are two
> potential values. As a result, it is a largely useless type whose sole
> redeeming feature is it allows developers to avoid having to define their
> own enum, but in most cases that aren't covered by Result<T> you actually
> *want* to define your own enum so you can attach meaning to the value.
>
> If it's not obvious, I'm very strongly against having a generic Either
> type, but I do want a Result<T> or Result<T,E>.
>
> -Kevin Ballard
>
> On Fri, Jan 22, 2016, at 10:22 PM, Developer via swift-evolution wrote:
>
> My overwhelming concern, after having a conversation with Chris, is that
> implementing a Result<T> means we are strongly implying a particular
> semantics and use case when we could generalize and abstract for no cost
> but an extra generic parameter.  In F#, Core.Choice can be used to build a
> Validation or Result monad, but the converse is impossible.
>
> ~Robert Widmann
>
> 2016/01/23 1:05、Rob Mayoff via swift-evolution <swift-evolution at swift.org>
> のメッセージ:
>
> Just added a section of motivating examples to the Either proposal.  Ping
> me if you have any more that I missed ('cause I'm sure I did miss a lot).
>
>
> https://github.com/typelift/swift-evolution/blob/either-or/proposals/0024-either.md#motivating-examples
>
>
>
> Your motivating examples (including all the projects you linked except
> "Any many more") overwhelmingly use the Either (or similar type) to
> represent success/failure. I'm not sure there's a single example where the
> names Left and Right actually make sense in the problem domain. I'm not
> 100% sure about func alternate in Madness/Alternation.swift. It definitely
> uses Left/Right to mean Failure/Result, but I couldn't tell if it also uses
> them as something else. Which makes those names all the more maddening.
>
> I checked my company's largest Scala project, which is over 300,000 lines.
> We use Scala's Try/Success/Failure in dozens of places. We use
> Either/Left/Right once, in a thrown-together report-generating script,
> which would probably have been written in awk or perl if it didn't need to
> read binary log files. (The ability of IntelliJ to reliably find all uses
> of a class or method is not to be underestimated. Hint hint, team Xcode.)
>
> I think a Result/Success/Failure type is warranted, but I'm very skeptical
> about generic Either/Left/Right.
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> *_______________________________________________*
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160126/e392e183/attachment.html>


More information about the swift-evolution mailing list