Syntax Error on "in"

ocaml compiler is really punishing me by giving me a very unhelpful error message. All it says is

54 | let x = AbstractStringSet.(add "foo" AbstractStringSet.empty) in
                                                                   ^^
Error: Syntax error

Here is my code. I am compiling it using “ocamlc foo.ml -o foo”
It is taken from Ocaml manual

type comparision = Less | Equal | Greater

module type ORDERED_TYPE = sig
  type t
  val compare : t -> t -> comparision
end

module OrderedString = struct
  type t = string
  let compare a b = 
    if a = b then 
      Equal
    else
      if a < b then 
        Less
      else
        Greater
end

module type SETFUNCTOR = 
  functor (Elt: ORDERED_TYPE) -> sig
    type element = Elt.t
    type set
    val empty : set
    val add : element -> set -> set
    val member : element -> set -> bool
  end

module Set = functor (Elt: ORDERED_TYPE) -> 
  struct
    type element = Elt.t
    type set = element list
    let empty = []
    let rec add x s = 
      match s with 
      [] -> [x]
      | hd :: tl -> 
        match Elt.compare hd x with 
        Equal -> s
        | Less -> x :: s
        | Greater -> hd :: add x tl
    let rec member x s = 
      match s with 
      [] -> false
      | hd :: tl -> 
        match Elt.compare hd x with 
        Equal -> true
        | Less -> false
        | Greater -> member x tl
  end

module AbstractSet = (Set: SETFUNCTOR)
module AbstractStringSet = AbstractSet(OrderedString)
let x = AbstractStringSet.add "foo" AbstractStringSet.empty in 
match AbstractStringSet.member "foo" x with 
| true -> print_endline "foo is found"
| false -> print_endline "foo not found"

You can’t have this kind of let binding at toplevel. Try:

let () =
  let x = AbstractStringSet.add "foo" AbstractStringSet.empty in 
  match AbstractStringSet.member "foo" x with
  > true -> print_endline "foo is found"
  > false -> print_endline "foo not found"

This works but why? because print_endline also returns unit. so why is let () = needed?

Alternatively, sticking a “;;” right before the line giving the error seems to make things work. I’m not going to go look thru the grammar to figure out why, but perhaps it’s b/c “expression-as-struct-item” is handled differently from other struct-items in the grammar.

OCaml has two different forms of let syntax. We can think of them as ‘let statement’ and ‘let expression’.

‘Let statement’ has the form let PAT = EXP and can exist at the module level only. Module level is directly inside a module. I.e. in a file or in a syntactic module.

‘Let expression’ has the form let PAT = EXP1 in EXP2 and can exist at the expression level only. Expression level is anything on the right-hand side of the equal sign in let ... = ....

4 Likes