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)
next 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).