(* Let us call an [intern] a function that takes a string [s] and returns
   a string that is logically equal to [s] -- i.e., it represents the same
   character sequence -- but is not necessarily physically equal to [s] --
   i.e., it may be stored in a different place in memory. Let us furthermore
   require that an intern perform maximal sharing., That is, if called twice
   with logically equal arguments, it must return physically equal results:
   [s1 = s2] implies [intern s1 == intern s2]. *)

type intern =
  string -> string

(* The call [new_intern()] creates a new intern, which has its own modifiable
   internal state; typically, a hash table, which contains all of the strings
   submitted so far to this intern. *)

val new_intern: unit -> intern