[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Need more polymorphism



Hi,

I'm trying to write a small actor-style program using Core.   I'm stuck on the 
fact that Pipe.create () returns a pair of weakly polymorphic values: 

> # let r,w = Pipe.create ();;
> val r : '_a Async.Std.Pipe.Reader.t = <abstr>
> val w : '_a Async.Std.Pipe.Writer.t = <abstr>

I'm using pipes as the mailboxes for my processes, and polymorphic variants as 
the message types.   I'm using the writer ends of the pipes in place of process 
IDs - to send a message to a process, you need a reference to the writer on its 
mailbox.

The problem is that the mailboxes inherit the weakly polymorphic property of 
the underlying pipe, even once the 'a has been resolved to my message type:

> # let proc_p = spawn p ();;
> val proc_p : _[< `Ping | `Stop ] -> unit Async_core.Deferred.t = <fun>

I have two different processes that both accept the `Stop message, but as soon 
as I try to put them together in the same list, for instance to pass them to a 
'stopper' process, the original processes lose their ability to receive 
anything apart from `Stop messages:

> # let proc_q = spawn q ();;
> val proc_q : _[< `Pong | `Stop ] -> unit Async_core.Deferred.t = <fun>
> # let l = [ proc_p; proc_q ];;
> val l : (_[< `Stop ] -> unit Async_core.Deferred.t) list = [<fun>; <fun>]
> # proc_p;;
> - : _[< `Stop ] -> unit Async_core.Deferred.t = <fun>

I found a note in the OCaml FAQ that shows how to work around this problem by 
eta-expansion 
(http://caml.inria.fr/resources/doc/faq/core.en.html#eta-expansion) but I don't 
see how to apply the same technique here.   I note that the signature of 
Pipe.create isn't weakly polymorphic, so it looks like it should be possible:

> # Pipe.create;;
> - : unit -> 'a Async.Std.Pipe.Reader.t * 'a Async.Std.Pipe.Writer.t = <fun>

Full code below.   Help! :)

Thanks,
Euan

---

open Core.Std
open Async.Std

(* Spawn a 'process' running f and return its mailbox *)
let spawn f args = 
        let r,w = Pipe.create () in
        don't_wait_for (f (r,w) args);
        Pipe.write w
        
(* Simple process *)
let rec p (r,w) () = 
        Pipe.read r >>= function
        | `Ok `Ping -> print_endline "ping"; p (r,w) ()
        | `Ok `Stop -> return (print_endline "stop")
        | `Eof      -> return (print_endline "eof" )
        
let rec q (r,w) () = 
        Pipe.read r >>= function
        | `Ok `Pong -> print_endline "pong"; q (r,w) ()
        | `Ok `Stop -> return (print_endline "stop")
        | `Eof      -> return (print_endline "eof" )
        
let _ =
        let rec proc_p = spawn p ()
        and proc_q = spawn q ()
        (* and l = [proc_p;proc_q]  -- with this line uncommented, the `Ping 
and `Pong lines below won't typecheck *)
        in
        ignore (proc_p `Ping);
        ignore (proc_q `Pong);
        never_returns (Scheduler.go())




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.