Enums in Racket

Our enum type ServerState has an underlying int type.

#lang racket

(define-type ServerState
  (Int one-of
       (StateIdle 0)
       (StateConnected 1)
       (StateError 2)
       (StateRetrying 3)))

The possible values for ServerState are defined as constants. Racket doesn’t have a direct equivalent of Go’s iota, but we can enumerate them manually.

(define StateIdle 0)
(define StateConnected 1)
(define StateError 2)
(define StateRetrying 3)

By implementing a function to convert ServerState values to strings, values of ServerState can be printed out or converted to strings.

(define state-name
  (hash
   StateIdle "idle"
   StateConnected "connected"
   StateError "error"
   StateRetrying "retrying"))

(define (state->string s)
  (hash-ref state-name s "unknown"))

If we have a value of type int, we cannot pass it to transition - the compiler will provide some degree of compile-time type safety.

(define (main)
  (let ((ns (transition StateIdle)))
    (displayln (state->string ns))
    (let ((ns2 (transition ns)))
      (displayln (state->string ns2)))))

transition emulates a state transition for a server; it takes the existing state and returns a new state.

(define (transition s)
  (case s
    [(StateIdle) StateConnected]
    [(StateConnected) StateIdle]
    [(StateRetrying) StateIdle]
    [(StateError) StateError]
    [else (error "unknown state")]))

To run this program, open a Racket REPL or script file and execute the main function.

(main)

The output of the program will look like this:

connected
idle