From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@sympa.inria.fr Delivered-To: caml-list@sympa.inria.fr Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by sympa.inria.fr (Postfix) with ESMTPS id EE0C67EE49 for ; Sat, 21 Sep 2013 01:22:06 +0200 (CEST) Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of pjfrey@sympatico.ca) identity=pra; client-ip=65.55.116.22; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="pjfrey@sympatico.ca"; x-sender="pjfrey@sympatico.ca"; x-conformance=sidf_compatible Received-SPF: Pass (mail2-smtp-roc.national.inria.fr: domain of pjfrey@sympatico.ca designates 65.55.116.22 as permitted sender) identity=mailfrom; client-ip=65.55.116.22; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="pjfrey@sympatico.ca"; x-sender="pjfrey@sympatico.ca"; x-conformance=sidf_compatible; x-record-type="v=spf1" Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of postmaster@blu0-omc1-s11.blu0.hotmail.com) identity=helo; client-ip=65.55.116.22; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="pjfrey@sympatico.ca"; x-sender="postmaster@blu0-omc1-s11.blu0.hotmail.com"; x-conformance=sidf_compatible X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AscBAG3YPFJBN3QWnGdsb2JhbABagz+De75qZxYOAQEBAQEGDQkJFCiCTwSBBwImAm8DiAWZao8DkiGBKZEsNYEAA5IUhxeEbBaPBQ X-IPAS-Result: AscBAG3YPFJBN3QWnGdsb2JhbABagz+De75qZxYOAQEBAQEGDQkJFCiCTwSBBwImAm8DiAWZao8DkiGBKZEsNYEAA5IUhxeEbBaPBQ X-IronPort-AV: E=Sophos;i="4.90,948,1371074400"; d="scan'208";a="33746540" Received: from blu0-omc1-s11.blu0.hotmail.com ([65.55.116.22]) by mail2-smtp-roc.national.inria.fr with ESMTP; 21 Sep 2013 01:22:05 +0200 Received: from BLU0-SMTP27 ([65.55.116.8]) by blu0-omc1-s11.blu0.hotmail.com with Microsoft SMTPSVC(6.0.3790.4675); Fri, 20 Sep 2013 16:22:05 -0700 X-TMN: [1p0+l6lCR8waDxM+zoVUeMjDWbZ6umxZ] X-Originating-Email: [pjfrey@sympatico.ca] Message-ID: Received: from [192.168.2.11] ([70.29.12.228]) by BLU0-SMTP27.phx.gbl over TLS secured channel with Microsoft SMTPSVC(6.0.3790.4675); Fri, 20 Sep 2013 16:22:04 -0700 From: Peter Frey To: caml-list@inria.fr Content-Type: text/plain; charset="UTF-8" Date: Fri, 20 Sep 2013 19:22:01 -0400 MIME-Version: 1.0 X-Mailer: Evolution 2.28.3 Content-Transfer-Encoding: 7bit X-OriginalArrivalTime: 20 Sep 2013 23:22:04.0399 (UTC) FILETIME=[377317F0:01CEB658] Subject: [Caml-list] Packing/Unpacking modules 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)