Ocaml error Printf.printf

let main() = 
let base = read_int () in
let num = read_int () in
if num = reverse num && (is_base base num) = true then Printf.printf "YES"
else if is_base base num = false then Printf.printf "ERROR" 
else Printf.printf"NO" 

This expression has type

     ('a -> 'b -> 'c, out_channel, unit, unit, unit, 'a -> 'b -> 'c)
   but an expression was expected of type
     ('a -> 'b -> 'c, out_channel, unit, unit, unit, unit)
   Type 'a -> 'b -> 'c is not compatible with type unit 

I've read the documentation, but it's still not clear how printf works in Ocaml. It works in toplevel. Maybe some library missing?

1 answer

  • answered 2018-03-11 12:57 octachron

    With a high probability the next line of your code is

    main ()

    or a similar toplevel expression, and this is the true source of your error. Toplevel expression needs to be introduced by ;;:

    ;; main ()

    Another idiom is to rather write

    let () = main ()

    to avoid introducing toplevel expressions at all

    Now, why did you get such a complicated type error? The answer is quite interestings and stems from the left-to-right bias of the typechecker and the flexibility of printf. Everything starts when we write:

     Printf.printf "ERROR" main ()

    Here, the type of Printf.printf is ('a, out_channel, unit) format -> 'a which means:

    • 'a: printf takes a format string plus as many argument as required by the format

    • out_channel: it writes on a out_channel

    • unit : ultimately, it returns unit.

    But then, when typing the function application, Printf.printf "Error" main (), the typechecker sees that Printf.printf is applied to three argument, it thus deduces that the type 'a can be expanded to 'b -> 'c -> 'd. But then, the typechecker looks at the type of the format argument "ERROR": ('e, 'f, 'e) format, it infers thus that the return type of the format should be 'b -> 'c -> 'd. But this is a contradiction with the fact that Printf.printf required unit as a return type, leading to your type error (after a bit of simplification):

     ('a -> 'b -> 'c, out_channel,'a -> 'b -> 'c) format
     but an expression was expected of type
     ('a -> 'b -> 'c, out_channel, unit) format
     Type 'a -> 'b -> 'c is not compatible with type unit