caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Jacques Garrigue <garrigue@math.nagoya-u.ac.jp>
To: geoffw@cis.upenn.edu
Cc: caml-list@inria.fr
Subject: Re: [Caml-list] Re: OO design
Date: Thu, 11 May 2006 15:21:18 +0900 (JST)	[thread overview]
Message-ID: <20060511.152118.223263747.garrigue@math.nagoya-u.ac.jp> (raw)
In-Reply-To: <44628062.6010509@cis.upenn.edu>

From: Dan Grossman

> A monadic approach (where each
> operation would return a "new" file) or linearity appears necessary for
> the latter.

And you can perfectly encode the monadic approach in ocaml.
In our case, we need the type of the monad to keep information about
open and closed files.
I include such a solution, which ensures the safety of file accesses,
at the end of this post. Note that file handles are indexed
statically, but you can use as many as you wish.

It should be safe with references (there is no file handle that you
can keep around, everything stays in the monad.) But beware of fancy
extensions, like continuations, that would allow you to capture your
environement, included files that were open when you created the
continuation...

From: Geoffrey Alan Washburn

> 	The only "solution" that I've seen that seems to actually solve the 
> "problem" is to write a small interpreted language for performing I/O, 
> but that is a bit heavy weight for general use.

I see indeed no other easy option if you have continuations in the
language.

Jacques

(* safeio.mli *)
type ('a,'b) monad    (* A monad, with action 'a, returning 'b *)
type ('a,'b) handle   (* A file handle to be used/modified *)
type input = [`In]    (* Permissions *)
type output = [`Out]
type active = [`In|`Out]
type closed = [`Closed]
type all_closed = <c: closed; n: all_closed> (* All files closed *)

val ch1 : (<c:'a;n:'b> -> <c:'c;n:'b>, 'a -> 'c) handle
val succ : ('a -> 'b, 'c) handle -> (<c:'d;n:'a> -> <c:'d;n:'b>, 'c) handle
val ch2 : (* shorthand for [succ ch1] *)
    (<c:'a; n: <c:'b; n:'c> > -> <c:'a; n: <c:'d; n:'c> >, 'b -> 'd) handle

val run : (all_closed -> all_closed, 'a) monad -> 'a

val open_in : ('a, closed -> input) handle -> string -> ('a, unit) monad
val open_out : ('a, closed -> output) handle -> string -> ('a, unit) monad
val close : ('a, [< active] -> closed) handle -> ('a, unit) monad
val input : ('a, input -> input) handle -> ('a, char option) monad
val output : ('a, output -> output) handle -> char -> ('a, unit) monad

val return : 'a -> ('b -> 'b, 'a) monad
val bind :
  ('a -> 'b, 'd) monad -> ('d -> ('b -> 'c, 'e) monad) -> ('a -> 'c, 'e) monad
val ( $ ) :
  ('a -> 'b, unit) monad -> ('b -> 'c, 'd) monad -> ('a -> 'c, 'd) monad

(* safeio.ml *)
type channel = Closed | In of in_channel | Out of out_channel
type channels = {mutable c: channel; mutable n: channels option}
type ('a,'b) monad = channels -> 'b
type ('a,'b) handle = int
(* Implementation left as exercise... *)

(* Example of use *)
open Safeio ;;

let rec copy2 () =
  bind (input ch1)
    (function None -> return ()
    | Some c -> bind (output ch2 c) copy2);;
val copy2 : unit ->
  (< c : input; n : < c : output; n : 'a > > ->
   < c : input; n : < c : output; n : 'a > >, unit) monad

let copy_file f1 f2 =
  open_in ch1 f1 $
  open_out ch2 f2 $
  copy2 () $
  close ch1 $
  close ch2 ;;

run (copy_file "a" "b") ;;


  parent reply	other threads:[~2006-05-11  6:22 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-05-05  9:35 David Baelde
2006-05-05 10:47 ` [Caml-list] " Gerd Stolpmann
2006-05-05 13:00 ` Remi Vanicat
2006-05-05 19:32   ` Andrej Bauer
2006-05-08  3:17 ` Jacques Garrigue
2006-05-08 21:29   ` David Teller
2006-05-08 21:36     ` Dan Grossman
2006-05-10  2:41       ` Geoffrey Alan Washburn
2006-05-10 16:17         ` [Caml-list] " Dan Grossman
2006-05-10 18:15           ` Geoffrey Alan Washburn
2006-05-10 18:44             ` [Caml-list] " Dan Grossman
2006-05-10 18:35           ` Shawn
2006-05-10 18:47             ` Till Varoquaux
2006-05-10 19:01               ` Shawn
2006-05-10 18:43           ` brogoff
2006-05-11  0:08             ` Geoffrey Alan Washburn
2006-05-11  5:45               ` [Caml-list] " Till Varoquaux
2006-05-11  6:21               ` Jacques Garrigue [this message]
2006-05-11 15:48                 ` Geoffrey Alan Washburn

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=20060511.152118.223263747.garrigue@math.nagoya-u.ac.jp \
    --to=garrigue@math.nagoya-u.ac.jp \
    --cc=caml-list@inria.fr \
    --cc=geoffw@cis.upenn.edu \
    /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).