What interests me is the connection of tagged unions and state machines. With tagged unions you can model values that depend on each other. An asynchronous task, for instance, can either be resolved with a value or rejected with a reason. But it cannot be both or neither. With a tagged union we can rule out the last two invalid states of such a task. This seems to be halfway to a state machine.

That's interesting. Could you give a code example of how tagged unions can model values that depend on each other? And also how you can rule out the last two invalid states.

I don't know ReasonML but I guess it has an Either type, right? Either<A, B> has two value constructors Left/Right, which can produce values of type Either<SomeProperType, B> and Either<A, SomeProperType> respectively. Consequently you cannot produce the invalid values Either<A, B> (no value at all) or Either<SomeProperType, SomeProperType (both values at the same time, aka the product). These values or states are ruled out by the way you modelled the data by using a tagged union. Values produced by Left and Right depend on each other, because they are mutually exclusive.

That's a pretty good description of the way variants work. OCaml/Reason does not have a built-in Either type, but they do have this "disjoint tagged unions" which can behave the same way.

The most common data type that models the Either type you describe (used in Haskell) is the Result type. It is modeled using the variant constructors Ok and Error. So the Reason code would look like:

moduleResult={typet('a,'e)=|Ok('a)|Error('e);};

And the type we have there is a bifunctor and a monad, just like Either.

That's exactly what's meant by "making impossible states unrepresentable" at the beginning of this article.

State machines have two things: states and transitions. With algebraic data types (tagged unions + records) we can model a state machine's states so that only valid states are represented. The next step would be to also model the transitions this way so that both invalid states as invalid transitions are excluded. This is also possible, but your code gets bloated quickly because you have to explicitly model every state and transition.

Log in to continue

We're a place where coders share, stay up-to-date and grow their careers.

What interests me is the connection of tagged unions and state machines. With tagged unions you can model values that depend on each other. An asynchronous task, for instance, can either be resolved with a value or rejected with a reason. But it cannot be both or neither. With a tagged union we can rule out the last two invalid states of such a task. This seems to be halfway to a state machine.

That's interesting. Could you give a code example of how tagged unions can model values that depend on each other? And also how you can rule out the last two invalid states.

I don't know ReasonML but I guess it has an

`Either`

type, right?`Either<A, B>`

has two value constructors`Left`

/`Right`

, which can produce values of type`Either<SomeProperType, B>`

and`Either<A, SomeProperType>`

respectively. Consequently you cannot produce the invalid values`Either<A, B>`

(no value at all) or`Either<SomeProperType, SomeProperType`

(both values at the same time, aka the product). These values or states are ruled out by the way you modelled the data by using a tagged union. Values produced by`Left`

and`Right`

depend on each other, because they are mutually exclusive.That's a pretty good description of the way variants work. OCaml/Reason does not have a built-in

`Either`

type, but they do have this "disjoint tagged unions" which can behave the same way.The most common data type that models the

`Either`

type you describe (used in Haskell) is the`Result`

type. It is modeled using the variant constructors`Ok`

and`Error`

. So the Reason code would look like:And the type we have there is a bifunctor and a monad, just like

`Either`

.That's exactly what's meant by "making impossible states unrepresentable" at the beginning of this article.

State machines have two things: states and transitions. With algebraic data types (tagged unions + records) we can model a state machine's states so that only valid states are represented. The next step would be to also model the transitions this way so that both invalid states as invalid transitions are excluded. This is also possible, but your code gets bloated quickly because you have to explicitly model every state and transition.