Does Lwt utilise data dependencies to increase paralleism - ocaml

I'm trying to work out what specifically lwt is doing in a couple of examples:
If I have:
let%lwt x = f () in
let%lwt y = g () in
return ()
Does this run f then g, or since y doesn't rely on x will it run both in parallel?

That particular example runs f () and g () in sequence, i.e. g () doesn't start until after the promise returned by f () is resolved.
The way to see this is, when looking at
let%lwt x = e in
e'
to realize that e' becomes the body of a callback, that will run only when x is available. So, in the code in the question, Lwt first sees:
(* Do this first. *)
let%lwt x = f () in
(* Do this once is available. *)
let%lwt y = g () in
return ()
and, once x is available, it is left with
(* Do this next. *)
let%lwt y = g () in
(* Do this once y is available. *)
return ()
To avoid this serialization, call f () and g () first, without any intervening let%lwt, bind variables to the promises x', y' these functions return, and wait on the promises:
let x' = f () in
let y' = g () in
let%lwt x = x' in
let%lwt y = y' in
return ()
(And to answer the title, Lwt does not use data dependencies. I don't think a library could have access to this kind of data dependency information).

In your code, no, because you are using Lwt.t as monad, rather than as an applicative.
Monads
You're probably already familiar with asynchronous IO and the functions Lwt.bind : 'a Lwt.t -> ('a -> 'b Lwt.t) -> 'b Lwt.t and Lwt.return : 'a -> 'a Lwt.t. Just in case, though, I will give a brief recap:
Lwt.bind promise callback awaits promise, and upon resolution, calls callback with the result, getting back another promise.
Lwt.return data creates a promise that resolves to data.
A monad is a generic type 'a t that has some function bind : 'a t -> ('a -> 'b t) -> 'b t and some function return : 'a -> 'a t. (These functions must also follow certain laws, but I digress.) Obviously, the type 'a Lwt.t with the functions Lwt.bind and Lwt.return form a monad.
Monads are a common functional programming pattern when one wants to represent some kind of "effect" or "computation," in this case asynchronous IO. Monads are powerful because the bind function lets later computations depend on the results of earlier ones. If m : 'a t represents some computation that results in 'a, and f : 'a -> 'b t is a function that uses an 'a to perform a computation that results in a 'b, then bind m f makes f depend on the result of m.
In the case of Lwt.bind promise callback, callback depends on the result of promise. The code in callback cannot run until promise is resolved.
When you write
let%lwt x = f () in
let%lwt y = g () in
return ()
you are really writing Lwt.bind (f ()) (fun x -> Lwt.bind (g ()) (fun y -> return ())). Because g () is inside the callback, it is not run until f () is resolved.
Applicatives
A functional programming pattern related to the monad is the applicative. An applicative is a generic type 'a t with a function map : ('a -> 'b) -> 'a t -> 'b t, the function return : 'a -> 'a t, and a function both : 'a t * 'b t -> ('a * 'b) t. Unlike monads, however, applicatives need not have bind : 'a t -> ('a -> 'b t) -> 'b t, meaning that with applicatives alone, later computations cannot depend on previous ones. All monads are applicatives, but not all applicatives are monads.
Because g () does not depend on the result of f (), your code can be rewritten to use both:
let (let*) = bind
let (and*) = both
let* x = f ()
and* y = g () in
return ()
This code translates to bind (fun (x, y) -> return ()) (both (f ()) (g ())). f () and g () appear outside the callback to bind, meaning that they are run immediately and can await in parallel. both combines f () and g () into a single promise.
The (let*) and (and*) operators are new to OCaml 4.08. If you are using an earlier version of OCaml, you can just write the translation directly.
Lwt.both in the documentation
The Lwt home page contains a code snippit using let* and and*
"Binding operators" (let* and and*) in the OCaml manual

Related

How to lift a value into a monad

I'm trying to use the Writer monad in OCaml.
module Writer : Monad = struct
type 'a t = 'a * string
let return x = (x, "")
let (>>=) m f =
let (x, s1) = m in
let (y, s2) = f x in
(y, s1 ^ s2)
end
The statement below works.
Writer.(>>=) (Writer.return 2) (fun x -> Writer.return 1);;
But the statement below does not.
Writer.(>>=) (Writer.return 2) (fun x -> (x, "inc"));;
Error: This expression has type 'a * 'b but an expression was expected of type
'c Writer.t
I tried
Writer.(>>=) (Writer.return 2) (fun x -> ((x, "inc") : int Writer.t))
Error: This expression has type 'a * 'b but an expression was expected of type
int Writer.t
What am I doing wrong here? How can I lift a value into a monad in OCaml?
As mentioned, the code works with:
Writer.(>>=) (Writer.return 2) (fun x -> Writer.return 1);;
This is because the signature that describes the monad, here Monad, probably has this form:
module type Monad = sig
type 'a t
val return : 'a -> 'a t
val ( >>= ) : 'a t -> ('a -> 'b t) -> 'b t
end
As the concrete implementation of 'a t is not yet known (the type module potentially serving several implementations), 'a t is "abstract".
One approach would therefore be to "de-abstract" it.
This is possible by reflecting in the signature of the Writer module that we want to implement the Monad module while not making the type 'a t abstract, in this way:
module Writer : Monad with type 'a t = 'a * string = struct
type 'a t = 'a * string
let return x = (x, "")
let (>>=) m f =
let (x, s1) = m in
let (y, s2) = f x in
(y, s1 ^ s2)
end
In this way, the type `'a t' will no longer be abstract.
As a side note, I personally think it's not particularly bad that the Writer (or Reader, or State) type is abstract. The fact that it's a couple seems to me to be an implementation detail, some piping that doesn't need to be leaked.
A more fundamental issue is that the signature constraint
module Any_monad : Monad
is almost always a mistake in OCaml.
Signature constraints remove information that stick out of the signature. Thus, after the constraint, Any_monad could be replaced by any other monads fulfilling the monad signature (if we temporarily exclude side-effectful monads). For instance, you could replace the Writer monad with this very useful monad:
module Nil = struct
type 'a t = unit
let bind x f = ()
let (>>=) = bind
let return x = ()
end
In other words, an useful monad needs to have functions that are not part of the monad interface. In the case of the Writer monad that would be a write function:
module Writer: sig
include Monad
val write: string -> unit t
val read: 'a t -> string
end = struct
...
end
Notice that we have extended the signature before using it as a constraint.
Once, those functions available, your original code can be rewritten as:
Writer.(return 2 >>= fun x -> write "inc" >>= fun () -> return x)
You're constraining your monad implementation to be a Monad but, in fact, you want its type to have the Writer signature. To put it in other words, you're upcasting your implementation and forgetting that it also have to implement operations specific to the Writer monad. Obviously, this renders your Writer monad useless as you can't write anything.
To get it fixed, we first need to define the Writer module type, a common definition might look something like this,
module type Writer = sig
type state
val write : state -> unit t
val read : 'a t -> state t
val listen : 'a t -> ('a * state) t
val exec : unit t -> state
include Monad with type 'a t := 'a t
end
Now you need to implement the newly added operations with the state type set to string and then you will be able to use your Writer monad without breaking its abstraction,
module Writer : Writer with type state = string = struct
type state = string
type 'a t = 'a * string
let return x = (x, "")
let (>>=) m f =
let (x, s1) = m in
let (y, s2) = f x in
(y, s1 ^ s2)
let write x = (),x
let read (_,x) = x
let listen (x,s) = ((x,s),s)
let exec (_,x) = x
end
There are few libraries that implement monads in OCaml, so you don't need to re-invent it by your own. You can try the monads library that we develop at CMU. It could be installed with
opam install monads

Implementing a function without using if-else statements

I would like to implement a function which gets as input f g a when f g are lambda functions and a is a parameter. The function should do as following:
fun foo f g a = if (g a) then (f a) else a;
> val foo = fn : ('a -> 'a) -> ('a -> bool) -> 'a -> 'a
Is it possible to somehow replace if-else with andalso,orelse, or some other method? I would like to implement a function without using if-else statements.
Edit: Looking for a way to combine two functions, one of them is 'a -> 'a while the other one is 'a -> bool.
if for some weird reason you don't want to use if-else you could pattern match to true/false. E.g. like that:
fun bar f g a = case (g a) of
true => (f a)
| false => a;
fun bari f g a = (fn true => f a | false => a)(g a);
But as Simon Shine already mentioned you may want to rephrase your question and describe the problem in a bigger picture if this is not what you are looking for.

How to convert CPS-style gcd computation to use the Continuation Monad

Let us consider the following implementation of the Continuation monad, for CPS-style computations yielding and integer:
module Cont : sig
type 'a t = ('a -> int) -> int
val return : 'a -> 'a t
val bind : 'a t -> ('a -> 'b t) -> 'b t
val callCC: (('a -> 'b t) -> 'a t) -> 'a t
end = struct
type 'a t = ('a -> int) -> int
let return x =
fun cont -> cont x
let bind m f =
fun cont -> m (fun x -> (f x) cont)
let callCC k =
fun cont -> k (fun x -> (fun _ -> cont x)) cont
end
How can we rewrite the CPS-style implementation of gcd computation (see How to memoize recursive functions?) and especially the memoization to take advantage of the Cont monad?
After defining
let gcd_cont k (a,b) =
let (q, r) = (a / b, a mod b) in
if r = 0 then Cont.return b else k (b,r)
I tried to use the type solver to give me cue about the type that the memoization function should have:
# let gcd memo ((a,b):int * int) =
Cont.callCC (memo gcd_cont (a,b)) (fun x -> x)
;;
val gcd :
(((int * int -> int Cont.t) -> int * int -> int Cont.t) ->
int * int -> (int -> 'a Cont.t) -> int Cont.t) ->
int * int -> int = <fun>
However I could not turn this hint into an actual implementation. Is someone able to do this? The logic behind using “callCC” in the memoization function is that if a value is found in the cache, then this is is an early exit condition.
I feel like the issue is that in his answer to How to memoize recursive functions?, Michael called CPS style what is not CPS style. In CPS style, the extra continuation argument k is used whenever one wants to return a value - the value is then applied to k instead.
This is not really what we want here, and not what implements:
let gcd_cont k (a,b) =
let (q, r) = (a / b, a mod b) in
if r = 0 then b else k (b,r)
Here, k is not used for returning (b is returned directly), it is used instead of performing a recursive call. This unwinds the recursion: within gcd_cont, one can think of k as gcd_cont itself, just like if let rec was used. Later on, gcd_cont can be turned into a truly recursive function using a fixpoint combinator, that basically "feeds it to itself":
let rec fix f x = f (fix f) x
let gcd = fix gcd_cont
(this is equivalent to the call function that Michael defines)
The difference with defining gcd directly using a let rec is that the version with unwinded recursion allows one to "instrument" the recursive calls, as the recursion itself is performed by the fixpoint combinator. This is what we want for memoization: we only want to perform recursion if the result is not in the cache. Thus the definition of a memo combinator.
If the function is defined with a let rec, the recursion is closed at the same time as defining the function, so one cannot instrument the recursive call-sites to insert memoization.
As a side note, the two answers basically implement the same thing: the only difference is the way they implement recursion in the fixpoint combinator: Michael's fixpoint combinator uses let rec, Jackson's one uses a reference, i.e. "Landin's knot" — an alternative way of implementing recursion, if you have references in your language.
Sooo, to conclude, I'd say implementing that in the continuation monad is not really possible / does not really make sense, as the thing was not CPS in the first place.

Lwt and recursive functions

Is it ok to use Lwt.return as the final call in a recursive function?
I have a function that compiles fine but does not run properly and it looks like the function f below. Please assume that there is no issue with any function provided as g in this example, I am basically just trying to find out if it is ok to have a function with the following form or if there is a better/simpler (and Lwt compliant) way of doing the following:
let rec f (x : string list) (g : string -> unit Lwt.t) =
match List.length x with
| 0 -> Lwt.return ()
| _ -> g (List.hd x) >>= fun () -> f (List.tl x) g
;;
val f : string list -> (string -> unit Lwt.t) -> unit Lwt.t = <fun>
I am pretty sure that I am doing it wrong. But the actual function I am using is much more complex than this example so I am having a difficult time debugging it.
First of all the correct way of dealing with lists in OCaml is deconstructing them with pattern matching, like this:
let rec f (xs : string list) (g : string -> unit Lwt.t) =
match xs with
| [] -> return ()
| x :: xs -> g x >>= fun () -> f xs g
The next step would be notice, that you're actually just perform iteration over a list. There is a Lwt_list.iter_s for this:
let f g xs = Lwt_list.iter_s g xs
That can simplified even more
let f = Lwt_list.iter_s
That means, that you even do not need to write such function, since it is already there.
And finally, there was no issues with recursion in your original implementation. The function that you've provided was tail recursive.
It depends whether g returns an lwt thread that is already computed such as return () or scheduled and woken up later by the lwt scheduler. In the former case, it's possible that the call to fun () -> f (List.tl x) g is made right away instead of being scheduled for later, and that could grow the stack depending on what optimizations are happening.
I don't think your code should rely on such tricky behavior. For this particular example, as suggested in #ivg's answer, you should use the functions from the Lwt_list module.
It's a good idea to look at the implementation of the Lwt_list module to see how it's done. The same advice goes for the OCaml standard library as well.

ocaml function takes function as parameter and output a function

I need to find a way to combine two functions and output them as one.
I have the following code where take in a list of function ('a->'a) list then output a function ('a->'a) using the List.fold_left.
I figured out the base case, but I tried a lot of ways to combine two functions. The output should have the type ('a -> 'a) list -> ('a -> 'a).
example output:
# pipe [] 3;;
- : int = 3
# pipe [(fun x-> 2*x);(fun x -> x + 3)] 3 ;;
- : int = 9
# pipe [(fun x -> x + 3);(fun x-> 2*x)] 3;;
- : int = 12
function:
let p l =
let f acc x = fun y-> fun x->acc in (* acc & x are functions 'a->'a *)
let base = fun x->x in
List.fold_left f base l
Since you know that you have to use a left fold, you now have to solve a fairly constrained problem: given two functions of type 'a -> 'a, how do you combine them into a single function of the same type?
In practice, there is one general way of combining functions: composition. In math, this is usually written as f ∘ g where f and g are the functions. This operation produces a new function which corresponds to taking an argument, applying g to it and then applying f to the result. So if h = f ∘ g, then we can also write this as h(x) = f(g(x)).
So your function f is actually function composition. (You should really give it a better name than f.) It has to take in two functions of type 'a -> 'a and produce another function of the same type. This means it produces a function of one argument where you produce a function taking two arguments.
So you need to write a function compose (a more readable name than f) of type ('a -> 'a) -> ('a -> 'a) -> ('a -> 'a). It has to take two arguments f and g and produce a function that applies both of them to its argument.
I hope this clarifies what you need to do. Figuring out exactly how to do it in OCaml is a healthy exercise.