Search code examples
ocamluser-defined-types

user defined type for strings which starts with Letter


I want to have user-defined type in Ocaml which represents strings which starts with English letter and afterwards can have letters or digits. Is it possible to define such custom type?


Solution

  • Jeffrey Scofield is right: there is no way in OCaml to define a type that would be the subset of strings verifying a given condition. You might however simulate that to some extent with a module and abstract or private data type, as in:

    module Ident : sig 
      type t = private string
      val create: string -> t
      val (^): t -> t -> t
      (* declare, and define below other functions as needed *)
    end = struct
      type t = string
      let create s = (* do some check *) s
      let (^) s1 s2 = create (s1 ^ s2)
    end;;
    

    Of course, the create function should check that the first char of s is a letter and the other ones letters or digits and raise an exception if this is not the case, but this is left a an exercise. This way, you know that any s of type Ident.t respects the conditions checked in create: by making the type synonym private in the signature, you ensure that you must go through one of the functions of Ident to create such value. Conversely (s:>string) is recognized as a string, hence you can still use all built-in functions over it (but you'll get back string, not Ident.t).

    Note however that there is particular issue with string: they are mutable (although that is bound to change in the upcoming 4.02 version), so that you can alter an element of Ident.t afterwards:

    let foo = "x0";;
    let bar = Ident.create foo;;
    foo.[0] <- '5';;
    bar;;
    

    will produce

    - : Ident.t = "50"
    

    If you restrict yourself to never modify a string in place (again this will be the default in the next OCaml's version), this cannot happen.