Automatically generate conversion functions from OCaml enums to integers

Suppose you have an OCaml enumeration of the kind:

type enum = A | B | C | D

Is there a standard way to easily derive (or implement with minimal redundancy) the following functions:

let int_of_enum = function
    | A -> 0
    | B -> 1
    | C -> 2
    | D -> 3

let enum_of_int = function
    | 0 -> A
    | 1 -> B
    | 2 -> C
    | 3 -> D
1 Like

If you want to go the unsafe route, I would guess that this is correct :

let int_of_enum (e:enum) = 
  (Obj.magic e : int)

let enum_of_int (i:int) = 
   (Obj.magic i : enum)

I have no idea what the range will be though, or how the constructors will be ordered.

2 Likes

This solution works indeed on my ocaml version and it has the benefit of being very fast. Is anyone aware of a safer solution that is guaranteed not to break in the future?

It seems to me that there is a pretty natural coding pattern underlying my question. For example, a simple and efficient way to represent a function of type enum -> t is to simply store an array of t values of size the length of the enum. The enum_of_int and int_of_enum functions would then be needed to manipulate such a representation.

2 Likes

You may be interested in ppx_deriving.enum:

# #require "ppx_deriving.enum" ;;
# type t = A | B | C | D [@@deriving enum] ;;

type t = A | B | C | D
val min : int = 0
val max : int = 3
val to_enum : t -> int = <fun>
val of_enum : int -> t option = <fun>
2 Likes

Thanks, this is exactly what I was looking for!
I knew ppx_enumerate but not ppx_enum.

1 Like

The only thing that is possibly missing from this solution in my opinion is an of_enum_exn: int -> t function that does not allocate an option and can be compiled into a quasi no-op by the compiler. But I am nitpicking here. :slight_smile:

1 Like