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

T.J. Usiyan griotspeak at gmail.com
Tue Jan 26 12:27:07 CST 2016


Thinking about it more, couldn't this syntax convey exactly what we want?

protocol EitherType {
  associatedtype L
  associated type R

  case left : L
  case right : R
}

On Tue, Jan 26, 2016 at 12:48 PM, Developer <devteam.codafi at gmail.com>
wrote:

> I love the idea, and we tried it in Tyro, but the loss of structure is
> worrying.  Plus, there isn't a way to specify that a protocol should apply
> only to an enum like there is with a class, nor that there should be proper
> kind constraints on implementors.  e.g.
>
> protocol EitherType {
>   associatedtype L
>   associatedtype R
>
>   var left : L? { get }
>   var right : R? { get }
> }
>
> This has a "valid" instance in every constructable type.
>
> extension Int : EitherType {
>   public L = String
>   public R = NSGlyphGenerator
>
>   // Omitted for brevity
> }
>
> You get the picture.
>
> ~Robert Widmann
>
> 2016/01/26 12:36、T.J. Usiyan <griotspeak at gmail.com> のメッセージ:
>
> 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/3aadd402/attachment.html>


More information about the swift-evolution mailing list