Reputation: 97
I have this code:
let n = read_int()
let rec fact n = if n=0 then 1 else n*fact(n-1)
let () = Printf.printf "%d factorial is %d.\n" n fact(n)
I compile and then the compiler says:
File "fat.ml", line 3, characters 23-46:
Error: This expression has type
('a -> 'b, out_channel, unit, unit, unit, 'a -> 'b)
CamlinternalFormatBasics.fmt
but an expression was expected of type
('a -> 'b, out_channel, unit, unit, unit, unit)
CamlinternalFormatBasics.fmt
Type 'a -> 'b is not compatible with type unit
How can I print the returned value?
Upvotes: 0
Views: 508
Reputation: 18892
The problem is a missing parenthesis around fact n
:
let () = Printf.printf "%d factorial is %d.\n" n (fact n)
works.
The reason behind the complicated type error that you got is that the compiler reads
let () = Printf.printf "%d factorial is %d.\n" n fact(n)
as
let () = Printf.printf "%d factorial is %d.\n" n fact n
In other words, for the compiler the function printf
is applied to 4 arguments: "%d factorial is %d.\n"
,n
, fact
and n
.
But the format string, let's call it fmt
, contains only two %d
specifiers. Thus the compiler also knows that there printf fmt
should takes two arguments and then returns unit. There is the discrepancy: Printf.printf fmt n fact
is expected to returns a function that can be applied to the last argument n
but it returns unit.
Or in other words,
Type 'a -> 'b is not compatible with type unit
The earlier part of the error
This expression has type ('a -> 'b, out_channel, unit, unit, unit, 'a -> 'b) CamlinternalFormatBasics.fmt but an expression was expected of type ('a -> 'b, out_channel, unit, unit, unit, unit) CamlinternalFormatBasics.fmt
is due to the fact that the type of format string is very flexible, and thus the typechecker only fails when it found out that it is not possible to print the format string and returns unit with the provided arguments.
Upvotes: 3