caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Peter Frey <pjfrey@sympatico.ca>
To: caml-list@inria.fr
Subject: [Caml-list] Packing/Unpacking modules
Date: Fri, 20 Sep 2013 19:22:01 -0400	[thread overview]
Message-ID: <BLU0-SMTP27EBB1458E2D6322877AD4A3220@phx.gbl> (raw)

The Ocaml type checker can occasionally be a bit, well, difficult to
fathom.  I am playing with a stream module a la Russo, which I found on
the internet.

There is a module type, a shorthand and a creation module:
         let s2 = mk_stream (module (LZ:StreamOps)) fromFn;; 
creates a stream which can be used (consumed) as expected in something
like:

let stm : char stream  = mk_stream (module LZ:StreamOps) fromFn in
  let module M = (val stm) in
  let rec aux strm n =
    if n = 1 then M.head strm
             else aux (M.tail strm) (pred n)
  in printf"%c\n" (aux M.stream n)

Now I want to return the module (stream) from a function. Ocaml cannot
allow this without re-packing (lest we get ...escapes its scope...) and
here is where the problems start. Packing modules does not appear to be
particularly intuitive.
I am showing my code (which does not work) first; the rest follows:

let q = let module M = (val s2:Stream with type a = char) in
                  (module  struct
                   include (val s2: Stream  with type a = char)
                   let stream = (M.tail (M.stream))
                   end : Stream with type a = char )

let _ = let module M = (val q:Stream with type a =char) in
Printf.printf"%c\n" (M.head M.stream)

This yields the error message
File "russo.ml", line 51, characters 27-172:
Error: Signature mismatch:
       ...
       Values do not match:
         val stream : M.a M.t
       is not included in
         val stream : a t
       File "dink.ml", line 17, characters 4-20: Expected declaration
       File "dink.ml", line 53, characters 23-29: Actual declaration

where lines 17 and 53 are, respectively,
   val stream : a t
   let stream = (M.tail (M.stream)) (* or even M.stream *)

M.a M.t is  type 'a t = char; ... I think ?

Here is the code of the streaming package; 
It is a translation by oleg@okmij.org of something demonstrated by
Claudio Russo (Google one of the comment lines).
Hopefully somebody will tell me how to re-pack the stream. The source
below can be pasted into ocaml (add ;; to make it start; it prints 'a')

thanks in advance
Peter Frey


  module type StreamOps =
  sig
    type 'a t
    val head : 'a t -> 'a
    val tail : 'a t -> 'a t
    val from : (int -> 'a) -> 'a t
    val map  : ('a -> 'b) -> 'a t -> 'b t
  end

  (* The type of a stream value.  We'll expose the type of elements
     ('a'), but leave the type of streams ('t') abstract. *)
  module type Stream =
  sig
    type a
    include StreamOps
    val stream : a t
  end

  (* A convenient shorthand for the type of stream values *)
  type 'a stream = (module Stream with type a = 'a)

  (* An implementation of streams as cons cells with lazy tails *)
  module LZ : StreamOps =
  struct
    type 'a t = Cons of 'a * 'a t Lazy.t
    let head (Cons (h, _)) = h
    let tail (Cons (_, lazy t)) = t
    let from f =
      let rec mk n = Cons (f n, lazy (mk (n + 1))) in
        mk 0
    let rec map f (Cons (h, lazy t)) = Cons (f h, lazy (map f t))
  end

  (* Create a stream from an implementation of the interface and an
indexing function *)
  let mk_stream : 'a.(module StreamOps) -> (int -> 'a) -> 'a stream
    = fun (type s) ops f ->
      (module 
       struct
         type a = s
         include (val ops : StreamOps)
         let stream = from f
       end : Stream with type a = s)

let its = 20
let str = "a234567890" ^ (String.make (its - 20) 'x' ) ^ "abcdefghij"
let fromFn = (fun x -> str.[x])
let s2 = mk_stream (module (LZ:StreamOps)) fromFn;;

let q = let module M = (val s2:Stream with type a = char) in
                  (module  struct
                   include (val s2: Stream  with type a = char)
                   (* let stream = M.stream (*(M.tail (M.stream))*) *)
                   end : Stream with type a = char )

let _ = let module M = (val q:Stream with type a =char) in
Printf.printf"%c\n" (M.head M.stream)








             reply	other threads:[~2013-09-20 23:22 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-09-20 23:22 Peter Frey [this message]
2013-09-21  0:17 ` Jeremy Yallop
2013-10-14 23:11 Peter Frey
2013-10-15 16:54 ` Drup

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=BLU0-SMTP27EBB1458E2D6322877AD4A3220@phx.gbl \
    --to=pjfrey@sympatico.ca \
    --cc=caml-list@inria.fr \
    /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).