caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: oleg@okmij.org
To: ivg@ieee.org, Didier.Cassirame@gmail.com
Cc: caml-list@inria.fr
Subject: [Caml-list] Higher order functors over tuples
Date: 6 Nov 2012 11:48:23 -0000	[thread overview]
Message-ID: <20121106114823.63702.qmail@www1.g3.pair.com> (raw)


Ivan Gotovchits wrote
> In general, the problem is to compute a tuple of objects that have
> types different, but conforming to the same interface
That seems to be the right problem for existentials -- which exist in
OCaml under the name of objects. Methods are the interface and fields
are private data. Of course we can get by with mere records -- but if
we have objects anyway we might as well use them.

> For example, we have several different data generator modules conforming
> to the signature

>    module type Generator =
>    sig
>      type t
>      type r
>      val create: unit  -> t
>      val result: t -> r option
>      val step:   t -> t option
>    end

> Each generator can be stepped forward and queried for a result. Generator
> can expire, in such case it will return None as a result. I want to make a
> ?list? of different generators and do some arbitary iterations on them.

Here is the implementation of that example using objects. It seems the
object implementation provides the same static assurances and
abstractions as the module implementation. Since generators can
expire, the effective number of generators does change
dynamically. The static tupling doesn't buy us much.

(* The interface of generators *)

class type ['r] generator = object ('self)
    method result : unit -> 'r option
    method step   : unit -> 'self option
end;;


(* Function `proceed' iterates over the generator and print results *)

let rec proceed : int generator -> unit = fun gen ->
  match gen#step () with
  | Some gen -> begin
      match gen#result () with
      | Some r -> print_int r; proceed gen
      | None   -> proceed gen
  end
  | None -> print_newline ();
      print_endline "generator finished"
;;

(* Just for a completness of the example a pair of simple generators: *)

class odd : int -> [int] generator = fun init -> object
    val v = init
    method step () = if v <= 10 then Some {< v = v + 2 >} else None
    method result () = if v <= 9 then Some v else None
end
;;

(* A different way to constrain the type *)
class even init = object (self : int #generator)
    val v = init
    method step () = if v <= 10 then Some {< v = v + 2 >} else None
    method result () = if v <= 8 then Some v else None
end
;;

(* Make a list of generators itself a generator *)

let gen_list : 'r generator list -> 'r generator = fun gens -> object
    val v = gens
    method step () = 
      let rec loop = function
	| [] -> None
	| h :: t -> 
	    begin match h#step () with 
            | None -> loop t
	    | Some gen -> Some {< v = t @ [gen]  >}
	    end
      in loop v

    (* find the first generator that gives a result *)
    method result () =
      let rec loop = function
	| [] -> None
	| h :: t -> 
	    begin match h#result () with 
            | None -> loop t
	    | r    ->  r
	    end
      in loop (List.rev v)
end
;;


let a_gen_list = gen_list [new even 0;
			   new odd (-1);
			   new even 0;
			   new even 0];;


proceed a_gen_list;;

212243446566878889999
generator finished


             reply	other threads:[~2012-11-06 11:48 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-11-06 11:48 oleg [this message]
2012-11-12  6:29 ` [Caml-list] " Ivan Gotovchits
2012-11-13  8:19   ` oleg
2012-11-15  3:17     ` Ivan Gotovchits
  -- strict thread matches above, loose matches on Subject: below --
2012-10-31  9:26 [Caml-list] " Ivan Gotovchits
2012-10-31 11:09 ` Didier Cassirame
2012-10-31 12:02   ` Ivan Gotovchits

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20121106114823.63702.qmail@www1.g3.pair.com \
    --to=oleg@okmij.org \
    --cc=Didier.Cassirame@gmail.com \
    --cc=caml-list@inria.fr \
    --cc=ivg@ieee.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).