Enums in OCaml
Enumerated types (enums) are a special case of sum types. An enum is a type that has a fixed number of possible values, each with a distinct name. The target language doesn’t have an enum type as a distinct language feature, but enums are simple to implement using existing language idioms.
Our enum type ServerState
has an underlying int
type.
type server_state =
| StateIdle
| StateConnected
| StateError
| StateRetrying
To map the enum values to their string representations, we can define a function.
let state_name = function
| StateIdle -> "idle"
| StateConnected -> "connected"
| StateError -> "error"
| StateRetrying -> "retrying"
By implementing a function similar to the fmt.Stringer
interface, values of server_state
can be printed out or converted to strings.
let string_of_server_state ss = state_name ss
If we have a value of type int
, we cannot pass it to transition
- the compiler will complain about type mismatch. This provides some degree of compile-time type safety for enums.
let transition = function
| StateIdle -> StateConnected
| StateConnected
| StateRetrying -> StateIdle
| StateError -> StateError
| _ -> failwith "unknown state"
Here’s the main function to emulate the state transitions and print the results.
let () =
let ns = transition StateIdle in
Printf.printf "%s\n" (string_of_server_state ns);
let ns2 = transition ns in
Printf.printf "%s\n" (string_of_server_state ns2)
The transition
function emulates a state transition for a server; it takes the existing state and returns a new state.
Suppose we check some predicates here to determine the next state…
$ dune exec ./enums.exe
connected
idle
Now that we understand how to define and use enums in OCaml, let’s learn more about the language.