Is [] a type or not?

I understand why let () = 1 + 2 leads to an error message when () is redefined. My question is why utop would be rewriting 1 + 2 as let () = 1 + 2, since it seems that the latter should lead to an error message even when () isn’t redefined.

The full rewriting rule for utop is that is first evaluated as

let _ () = let module _ = struct <expr> end in ()

in order to check the expression without evaluating it.

Slightly off-topic, but another way I find redefining [] and (::) useful locally is when combining them with GADTs and existential types to implement kinds of DSLs.

A recent example was for heterogenous pretty printing of parameters:

    let module M = struct
      type t =
        | [] 
        | (::) : ((formatter -> 'a -> unit) * 'a) * t -> t

      let rec pp_ls fmt = function
        | [] -> ()
        | (pp, v) :: [] -> pp fmt v
        | (pp,v) :: tl -> pp fmt v; pp_print_string fmt ","; pp_print_space fmt (); pp_ls fmt tl
    end in

and then instantiating them:

(pp_rule "Read" M.[pp_print_string, var; pp_print_int, offset])

(where var is of type string, and offset of type int).

1 Like