I have encountered some errors when using Lwt_main.run()
. Basically I have two infinite loops with type unit -> 'a Lwt.t = <fun>
and when I start both loops I receive errors. I am using these in the context that one loop is a writer loop and the other is a reader loop. Basically I have to update some data with the writer much more often than I use it with the reader. The errors I receive can be illustrated with the code below.
let rec p1 () =
Lwt_io.print "1\n"
>>= fun () -> Lwt_unix.sleep 1.0
>>= p1
;;
val p1 : unit -> 'a Lwt.t = <fun>
let rec p5 () =
Lwt_io.print "5\n"
>>= fun () -> Lwt_unix.sleep 5.0
>>= p5
;;
val p5 : unit -> 'a Lwt.t = <fun>
Lwt_main.run(p1(); p5());;
Characters 13-17:
Warning 10: this expression should have type unit.
Characters 13-17:
Warning 10: this expression should have type unit.
I can run the Lwt_main.run statements as follows without errors but it seems that this solution is just masking the warning with the wildcard instead of fixing the warning.
let _ = Lwt_main.run(p1())
let _ = Lwt_main.run(p5())
What is the proper use of Lwt_main.run()
in this context so that I can fix the errors instead of just masking them with the wildcard character?
First of all it is not an error, but warning. It states that expression that is terminated with ;
doesn't evaluate to a value of type unit
as expected. In your case you have two expressions p1 ()
that evaluates to unit Lwt.t
and p5 ()
that evaluates to the same type. Obviously they do not have type unit
, so that you can't put ;
after p1 ()
or p5 ()
. Since both of them are lwt threads, and what you want (I suspect) is to run them in parallel, then you need to use Lwt.pick
function, or its infix equivalent <&>
:
let () = Lwt_main.run (p1 () <&> p5 ())
On the other hand, if you want to serialize this threads, i.e., to run one after another, not in parallel, then you need to bind them using >>=
operation, or, if you have enabled syntax support, then you can use >>
syntax, thats actually stands for monadic semicolon.