Ocaml Lwt type confusion

258 Views Asked by At

I'm confused why the Lwt print function Lwt_io.print has type string -> unit Lwt.t But if I run Lwt_io.print "a" >>= fun () -> Lwt_io.print "b";; the result is that "ab" is printed and type unit is returned.

I would imagine that this would be a type error since Lwt_io.print returns unit Lwt.t not unit. Why is the second part of the thread called?

2

There are 2 best solutions below

2
On BEST ANSWER

I suspect you are getting confused because utop is being smart.

If you look at the utop documentation, it is written

when using the lwt or async libraries, UTop will automatically wait for ['a Lwt.t] or ['a Deferred.t] values and return the ['a] instead

Which is why

Lwt_io.print "a" >>= fun () -> Lwt_io.print "b";;

appears to be of type unit. To see the real type, try the following

let res = Lwt_io.print "a" >>= fun () -> Lwt_io.print "b";;
#show res;;

You will see that as you get what you were expecting, a unit Lwt.t

Update:

Just to make things clear about types, we have

let f = fun () -> Lwt_io.print "b"
val ( >>= ) : 'a Lwt.t -> ('a -> 'b Lwt.t) -> 'b Lwt.t
val print : string -> unit Lwt.t
val f : unit -> unit Lwt.t

Lwt_io.print "a" therefore returns a unit Lwt.t. This is the first parameter of (>>=), and 'a is therefore unit. The second parameter of (>>=) is f. f takes a unit, which is what we needed, as 'a is unit. It returns a unit Lwt.t, so 'b is also unit. This means that the final result will be a unit Lwt.t.

0
On

On Utop[1], toplevel lwt and async expressions are automatically run with Lwt_main.run and Thread_safe.block_on_async_exn respectively.

To disable that, run

UTop.set_auto_run_lwt false;; (* for lwt *)
UTop.set_auto_run_async false;; (* for async *)

[1] https://github.com/ocaml-community/utop/blob/c898602882e032ec3c5c8315d260cfbdb2f9eeb4/src/lib/uTop.mli#L114-L133