caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Alan Schmitt <alan.schmitt@polytechnique.org>
To: "lwn" <lwn@lwn.net>, "cwn"  <cwn@lists.idyll.org>, caml-list@inria.fr
Subject: [Caml-list] Attn: Development Editor, Latest OCaml Weekly News
Date: Tue, 28 Jun 2022 09:37:16 +0200	[thread overview]
Message-ID: <87sfnpw85v.fsf@m4x.org> (raw)

[-- Attachment #1: Type: text/plain, Size: 9063 bytes --]

Hello

Here is the latest OCaml Weekly News, for the week of June 21 to 28,
2022.

The mailing list mode of discuss.ocaml.org seems to have been down for a
few days, so I had to manually scrape the messages. My apologies if I
missed any.

Table of Contents
─────────────────

An amusing use of first-class modules: reading from plaintext and compressed files
Lwt.5.6.0 (and other Lwt packages)
Old CWN


An amusing use of first-class modules: reading from plaintext and compressed files
══════════════════════════════════════════════════════════════════════════════════

  Archive:
  <https://discuss.ocaml.org/t/an-amusing-use-of-first-class-modules-reading-from-plaintext-and-compressed-files/10073>


Chet_Murthy explained
─────────────────────

  I was recently trying to write a thing in Rust, and having problems,
  so I wrote the same thing in OCaml, just to make sure that it was
  doable. I thought I’d post about it, b/c maybe it’s an example of what
  we’ll find more tractable, once we have modular implicits.

  The problem: I have both compressed and plaintext files, and I want to
  run a function over the uncompressed contents. I’d like a combinator
  that I can apply to the filename and the function, that will do the
  work of opening the file, calling the function, closing the file, etc.

  This isn’t so hard.

  1. define a type of READER (and two instances for plaintext and
     gzipped). This is the equivalent of Rust’s “io::BufRead”.

     ┌────
     │ module type READER =
     │   sig
     │     type in_channel
     │     val open_in : string -> in_channel
     │     val input_char : in_channel -> char
     │     val close_in : in_channel -> unit
     │   end
     │ let stdreader = (module Stdlib : READER) ;;
     │ let gzreader = (module Gzip : READER) ;;
     └────

  2. then define a type of “in channel user” (“ICUSER”) and the generic
     version of it

     ┌────
     │ module type ICUSER = sig
     │   type in_channel
     │   val use_ic : in_channel -> unit
     │ end
     │ module type GENERIC_ICUSER = functor (R : READER) -> (ICUSER with type in_channel = R.in_channel)
     └────

  3. then define our function that takes a generic in_channel, and uses
     it – “Cat”

     ┌────
     │ module Cat(R : READER) : ICUSER with type in_channel = R.in_channel = struct
     │   type in_channel = R.in_channel
     │   let use_ic ic =
     │   let rec rerec () =
     │     match R.input_char ic with
     │       c -> print_char c ; rerec ()
     │     | exception End_of_file -> ()
     │   in rerec ()
     │ end
     └────

  4. And then write our “with_input_file” function, that takes a
     filename, the function from #3, and applies it to either a normal
     in_channel, or one produced from a gzip-reader.

     ┌────
     │ let with_input_file fname (module R : GENERIC_ICUSER) =
     │   let (module M : READER) =
     │     if Fpath.(fname |> v |> has_ext "gz") then
     │       gzreader
     │     else stdreader in
     │   let open M in
     │   let ic = M.open_in fname in
     │   let module C = R(M) in
     │   try let rv = C.use_ic ic in close_in ic ; rv
     │   with e -> close_in ic ; raise e
     └────

  And now we can use it:

  ┌────
  │ with_input_file "/etc/passwd" (module Cat) ;;
  │ with_input_file "foo.gz" (module Cat) ;;
  └────

  Easy-peasy. I don’t remember enough about the modular implicits
  proposal to remember if this can be cast in the supported language
  there, so I suppose I should get some version of that code (or the
  newer versions from others) up-and-running, and see if this can be
  made to work.


hyphenrf asked and Chet_Murthy replied
──────────────────────────────────────

        can’t we get rid of the `GENERIC_ICUSER' requirement and
        just ask for functions that take a packed module of type
        `READER'

        by that I mean the signature of `with_input_file' becomes
        `string -> ((module READER) -> 'a) -> 'a'

  It’s a good question, and as a newbie user of first-class modules, I
  don’t know the typing rules well enough to answer. But I did try:

  ┌────
  │ let with_input_file' fname f =
  │   let (module M : READER) =
  │     if Fpath.(fname |> v |> has_ext "gz") then
  │       gzreader
  │     else stdreader in
  │   let open M in
  │   let ic = M.open_in fname in
  │   f (module M : READER) ic
  └────

  and got

  ┌────
  │ File "ioabs.ml", line 96, characters 24-26:
  │ 96 |   f (module M : READER) ic
  │ 			     ^^
  │ Error: This expression has type M.in_channel
  │        but an expression was expected of type 'a
  │        The type constructor M.in_channel would escape its scope
  └────

  ETA: I remember in the modular implicits paper, that there was a lot
  of wrappering code in structs (that didn’t start off in structs). I
  wonder if that’s evidence that you really do have to “push up” code to
  the module level in order to make it work.


octachron then said
───────────────────

  You don’t need modular implicits to simplify your code. Your packed
  module type is equivalent to:

  ┌────
  │ type channel = { input_char: unit -> char; close_in: unit -> unit }
  │ type channel_generator = string ->  channel
  └────

  We could go fancy and manifest the type with an existential

  ┌────
  │ type 'a channel =
  │   { open_fn: string -> 'a; input_char: 'a -> char; close_in: 'a -> unit }
  │ type chan = Any: 'a channel -> chan
  └────

  but this has mainly the advantage to illustrate the fact that you are
  never using the non-existentially qualified `'a channel' which means
  that in the current version of your code, modular (explicits or)
  implicits is not a good fit: we are not selecting a module to provide
  functions for a type, we have an object (aka an existentially
  qualified record) with some hidden inner type that we never need to
  know.


c-cube later said
─────────────────

  I think it’s kind of counter-productive to want a `in_channel' type at
  all. This is what I’ve been doing, more and more:

  ┌────
  │ module type INPUT = sig
  │   val read_char : unit -> char
  │   val read : bytes -> int -> int -> int
  │   val close : unit -> unit
  │ end
  │ 
  │ type input = (module INPUT)
  │ 
  │ let open_file (filename:string) : input =
  │   let ic = open_in filename in
  │   (module struct
  │     let read_char() = input_char ic
  │     let read = input ic
  │     let close() = close_in ic
  │  end)
  │ 
  │ 
  │ let do_sth (module IN:INPUT) =
  │   IC.read_char ();
  │   IC.read …
  └────

  This behaves like classic objects in other languages and there’s no
  complicated typing going on (what with each implementation having its
  own channel type).


Lwt.5.6.0 (and other Lwt packages)
══════════════════════════════════

  Archive:
  <https://discuss.ocaml.org/t/ann-lwt-5-6-0-and-other-lwt-packages/10077>


raphael-proust announced
────────────────────────

  It is a real pleasure to announce the release of Lwt version 5.6.0 as
  well as Lwt-domain.0.2.0, Lwt-ppx.2.1.0 and Lwt-react.1.2.0. With this
  release Lwt is now compatible with OCaml version 5.

  <https://github.com/ocsigen/lwt/releases/tag/5.6.0>

  Thank you to the many contributors for the fixes, the improvements,
  and the OCaml5 compatibility! Check out the changelog for full details
  on each contribution.


Old CWN
═══════

  If you happen to miss a CWN, you can [send me a message] and I'll mail
  it to you, or go take a look at [the archive] or the [RSS feed of the
  archives].

  If you also wish to receive it every week by mail, you may subscribe
  [online].

  [Alan Schmitt]


[send me a message] <mailto:alan.schmitt@polytechnique.org>

[the archive] <https://alan.petitepomme.net/cwn/>

[RSS feed of the archives] <https://alan.petitepomme.net/cwn/cwn.rss>

[online] <http://lists.idyll.org/listinfo/caml-news-weekly/>

[Alan Schmitt] <https://alan.petitepomme.net/>


[-- Attachment #2: Type: text/html, Size: 27825 bytes --]

             reply	other threads:[~2022-06-28  7:37 UTC|newest]

Thread overview: 112+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-28  7:37 Alan Schmitt [this message]
  -- strict thread matches above, loose matches on Subject: below --
2022-07-26 17:54 Alan Schmitt
2022-07-19  8:58 Alan Schmitt
2022-07-12  7:59 Alan Schmitt
2022-07-05  7:42 Alan Schmitt
2022-06-21  8:06 Alan Schmitt
2022-06-14  9:29 Alan Schmitt
2022-06-07 10:15 Alan Schmitt
2022-05-31 12:29 Alan Schmitt
2022-05-24  8:04 Alan Schmitt
2022-05-17  7:12 Alan Schmitt
2022-05-10 12:30 Alan Schmitt
2022-05-03  9:11 Alan Schmitt
2022-04-26  6:44 Alan Schmitt
2022-04-19  5:34 Alan Schmitt
2022-04-12  8:10 Alan Schmitt
2022-04-05 11:50 Alan Schmitt
2022-03-29  7:42 Alan Schmitt
2022-03-22 13:01 Alan Schmitt
2022-03-15  9:59 Alan Schmitt
2022-03-01 13:54 Alan Schmitt
2022-02-22 12:43 Alan Schmitt
2022-02-08 13:16 Alan Schmitt
2022-02-01 13:00 Alan Schmitt
2022-01-25 12:44 Alan Schmitt
2022-01-11  8:20 Alan Schmitt
2022-01-04  7:56 Alan Schmitt
2021-12-28  8:59 Alan Schmitt
2021-12-21  9:11 Alan Schmitt
2021-12-14 11:02 Alan Schmitt
2021-11-30 10:51 Alan Schmitt
2021-11-16  8:41 Alan Schmitt
2021-11-09 10:08 Alan Schmitt
2021-11-02  8:50 Alan Schmitt
2021-10-19  8:23 Alan Schmitt
2021-09-28  6:37 Alan Schmitt
2021-09-21  9:09 Alan Schmitt
2021-09-07 13:23 Alan Schmitt
2021-08-24 13:44 Alan Schmitt
2021-08-17  6:24 Alan Schmitt
2021-08-10 16:47 Alan Schmitt
2021-07-27  8:54 Alan Schmitt
2021-07-20 12:58 Alan Schmitt
2021-07-06 12:33 Alan Schmitt
2021-06-29 12:24 Alan Schmitt
2021-06-22  9:04 Alan Schmitt
2021-06-01  9:23 Alan Schmitt
2021-05-25  7:30 Alan Schmitt
2021-05-11 14:47 Alan Schmitt
2021-05-04  8:57 Alan Schmitt
2021-04-27 14:26 Alan Schmitt
2021-04-20  9:07 Alan Schmitt
2021-04-06  9:42 Alan Schmitt
2021-03-30 14:55 Alan Schmitt
2021-03-23  9:05 Alan Schmitt
2021-03-16 10:31 Alan Schmitt
2021-03-09 10:58 Alan Schmitt
2021-02-23  9:51 Alan Schmitt
2021-02-16 13:53 Alan Schmitt
2021-02-02 13:56 Alan Schmitt
2021-01-26 13:25 Alan Schmitt
2021-01-19 14:28 Alan Schmitt
2021-01-12  9:47 Alan Schmitt
2021-01-05 11:22 Alan Schmitt
2020-12-29  9:59 Alan Schmitt
2020-12-22  8:48 Alan Schmitt
2020-12-15  9:51 Alan Schmitt
2020-12-01  8:54 Alan Schmitt
2020-11-03 15:15 Alan Schmitt
2020-10-27  8:43 Alan Schmitt
2020-10-20  8:15 Alan Schmitt
2020-10-06  7:22 Alan Schmitt
2020-09-29  7:02 Alan Schmitt
2020-09-22  7:27 Alan Schmitt
2020-09-08 13:11 Alan Schmitt
2020-09-01  7:55 Alan Schmitt
2020-08-18  7:25 Alan Schmitt
2020-07-28 16:57 Alan Schmitt
2020-07-21 14:42 Alan Schmitt
2020-07-14  9:54 Alan Schmitt
2020-07-07 10:04 Alan Schmitt
2020-06-30  7:00 Alan Schmitt
2020-06-16  8:36 Alan Schmitt
2020-06-09  8:28 Alan Schmitt
2020-05-19  9:52 Alan Schmitt
2020-05-12  7:45 Alan Schmitt
2020-05-05  7:45 Alan Schmitt
2020-04-28 12:44 Alan Schmitt
2020-04-21  8:58 Alan Schmitt
2020-04-14  7:28 Alan Schmitt
2020-04-07  7:51 Alan Schmitt
2020-03-31  9:54 Alan Schmitt
2020-03-24  9:31 Alan Schmitt
2020-03-17 11:04 Alan Schmitt
2020-03-10 14:28 Alan Schmitt
2020-03-03  8:00 Alan Schmitt
2020-02-25  8:51 Alan Schmitt
2020-02-18  8:18 Alan Schmitt
2020-02-04  8:47 Alan Schmitt
2020-01-28 10:53 Alan Schmitt
2020-01-21 14:08 Alan Schmitt
2020-01-14 14:16 Alan Schmitt
2020-01-07 13:43 Alan Schmitt
2019-12-31  9:18 Alan Schmitt
2019-12-17  8:52 Alan Schmitt
2019-12-10  8:21 Alan Schmitt
2019-12-03 15:42 Alan Schmitt
2019-11-26  8:33 Alan Schmitt
2019-11-12 13:21 Alan Schmitt
2019-11-05  6:55 Alan Schmitt
2019-10-15  7:28 Alan Schmitt
2019-09-03  7:35 Alan Schmitt

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=87sfnpw85v.fsf@m4x.org \
    --to=alan.schmitt@polytechnique.org \
    --cc=caml-list@inria.fr \
    --cc=cwn@lists.idyll.org \
    --cc=lwn@lwn.net \
    --subject='Re: [Caml-list] Attn: Development Editor, Latest OCaml Weekly News' \
    /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

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