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