DiscriminatedUnion Protocol

updated with a bit of motivation

That is a strange state machine definition to me, where instead of being defined by (State, Input) -> State or similar you are just defining valid state transitions (State -> Set<State>) and letting the user blindly try to transition to any state. So all the logic about state transitions has to live and be duplicated outside of the type, or the user will have to do try/catch trial and error, etc. Would this be a common approach?

A stronger example for me, on the same theme, might be to use the same approach to define the set of valid inputs by state rather than valid transitions. This would contrast with the standard approach of including an error state in the state machine that any invalid inputs lead to, and may lead to a nicer way to specify transitions because you would only need to define valid transitions.

Thank you for the feedback.

  • I'm not sure what you mean by 'blindly' transition, here. I guess you mean that the API exposed to the end user doesn't–somehow–guard at compile time? I'd like that and have a few ideas that could address the concern but those are… larger requests. ([Proposal] Enum subsets for example)
  • If you run the example that I've provided… it does a runtime check. 'automatically'. That is useful
  • The example that you've given seems valid and good which makes it seem like the motivation in the pitch did, at least, convey a bit of the core value in the proposal

Oh, sorry. By “blindly transition” I mean that you usually drive a state machine using some sort of separate input (see some examples here), not by just trying to manually transition between states and being stopped. This keeps all the transition/behavioural information inside the type so users can just observe inputs and outputs, rather than duplicating that logic outside of the type. e.g. if you wanted to add a “retry once on error” to your loading example, you would want that information to be encapsulated inside the state machine to present a nicer interface. The example given is more of a directed graph (i.e. just encoding edges/valid transitions) than what I would think of as a state machine.

You would have/want to write something like what I have provided to be driven by the input that you're talking about, no? The code provided is, as you've pointed out, not the entire picture but it is one part that is improved by having this feature.

Sure, as I said originally, if validTransitions: [State: Set<State>] was instead validInputs: [State: Set<Inputs>] then that makes more sense to me as a state machine model.

I‘m not 100% sure but it seems that the proposed design will eventually fail. Here is a non-valid Swift code today, but is accepted as valid by the enum normalization proposal, which means that the current proposal must tolerate it as well.

enum E {
  case a(Int)
  case a(String)
}

Can you elaborate how the proposed design will handle this case?

right now? my answer would probably be some sort of diagnostic and requiring that you write your own discriminant and lose synthesis.

in other words, when we can't generate one for you, we won't. The point of the proposal is not only synthesis. It provides a unifying protocol for some pattern matchable types.

1 Like