Search code examples
ocamlutopocaml-lwt

Ocaml Lwt type confusion


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?


Solution

  • 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.