Mailing list for all users of the OCaml language and system.
 help / color / mirror / Atom feed
From: Michael Walter <michael.walter@gmail.com>
To: Jacques Garrigue <garrigue@math.nagoya-u.ac.jp>
Cc: JEFHEN@safeco.com, caml-list@inria.fr
Subject: Re: [Caml-list] environment idiom
Date: Thu, 9 Dec 2004 01:02:16 -0500	[thread overview]
Message-ID: <877e9a170412082202790e2cfb@mail.gmail.com> (raw)
In-Reply-To: <20041209.134735.79249569.garrigue@math.nagoya-u.ac.jp>

Is there such thing as implicit parameters in O'caml, basically
variables with dynamic extent. Could be (partially?) statically
checked, too, no?

Cheers,
Michael


On Thu, 09 Dec 2004 13:47:35 +0900 (JST), Jacques Garrigue
<garrigue@math.nagoya-u.ac.jp> wrote:
> From: "HENRIKSON, JEFFREY" <JEFHEN@safeco.com>
> 
> 
> 
> > I am interested in the idiom of passing a number of parameters by some
> > kind of "environment" variable.  Think of a web server with hundredes of
> > functions for processing markup and other things, only 3 of which need
> > to detect the browser.  It's bad maintainability to explicitly pass
> > browserid through hundreds of functions which don't use it.  And of
> > course, we must separate the state of the calling threads so as to not
> > cheat with global variables or some such thing.
> >
> > There seem to be two main candidates for such an idiom in Ocaml, objects
> > and polymorphic variants.
> 
> [...]
> 
> > And the polymorphic variant way, roughly:
> > let h = Hashtbl.create 10;;
> >
> > Hashtbl.add h `Banana (`Banana "b");;
> > Hashtbl.add h `Apple (`Apple "a");;
> > Hashtbl.add h `Pear (`Pear "p");;
> 
> This seems a bit of an overkill: I would rather write directly
>   let env = [`Banana "b"; `Apple "a"; `Pear "p"]
> Which would give you more or less the same typing.
> 
> > Each of these idioms has its own advantage:
> >
> > In the object way the compiler verifies that the functions are passed
> > objects which contain all their needed configuration keys.  But if I
> > understand correctly, we must at some point construct an environment
> > object which has _all_ the keys, even if we don't know them yet.  We can
> > add by mutation, but we cannot simply leave them out and add them as we
> > get to functions which need them.
> 
> A common way to do it would be to have a class defining defaults,
> and inherit and override it in your environment object.
> I'm not sure of how you intend to use your environment.
> But you're right that it is difficult to make changes incremental,
> since ocaml have no incrementally extendable records.
> 
> Note also that while you cannot extend an object, you can extend a
> class, and you can use local modules to define classes locally.
> Yet, you cannot pass classes (or modules) to functions, so this does not
> solve your problem.
> 
> > In the pv way the construction can be made incremental.  Ie, if we
> > changed the hashtable to a list or immutable queue, we could add keys as
> > we go.  But at least as I have it set up, the variants are not placing
> > restrictions on the existence of keys in the environment, other than
> > saying "we can understand at least this many keys," which is of course
> > meaningless.  Is there a way to turn the typing around to say "we
> > require at least these keys"?
> 
> No: any variant type is a subtype of a variant type containing more
> keys, so you would be able to cheat anyway.
> 
> > In general, what are the typing and run-time limitations around each
> > way?
> 
> I think you've described them correctly: objects offer exact typing,
> but cannot be extended incrementally, and lists of porlymorphic
> variants enforce typing but do not guarantee what keys are defined.
> 
> In terms of efficiency, objects generate more code, but performance should
> be comparable.
> 
> Note that ocaml contains a third way to do that, which in some cases is
> more natural. You can use labelled arguments. This means that you must
> pass all the arguments explicitly, but you are no longer restricted by
> their order. Some arguments may be optional.
> Depending on your goal, this may be the safest way to pass parameters.
> 
> let bar ~pear s = pear^s
> let foo ~apple ~banana ~pear s = bar ~pear (apple^banana^s)
> 
> You may look at code in lablgtk2 for clever ways to handle long lists
> of parameters this way. (But this doesn't fit your web server
> example.)
> 
> A last way, which could work very well with your web server example,
> is to use records in place of objects, and update them using
> with. Then you can use clever typing.
> 
> module Option : sig
>   type (+'a,+'b) t
>   type abs = [`abs|`pre]
>   type pre = [`pre]
>   val none : ('a, abs) t
>   val some : 'a -> ('a, 'b) t
>   val get : ('a, pre) t -> 'a
> end = struct
>   type ('a,'b) t = 'a option
>   type abs = [`abs|`pre]
>   type pre = [`pre]
>   let none = None
>   let some x = Some x
>   let get = function Some x -> x | None -> assert false
> end
> 
> open Option
> 
> type ('a,'b,'c) env =
>   {apple: (string, 'b) t; banana: (string, 'a) t; pear: (string, 'c) t}
> 
> # let empty = {apple=none; banana=none; pear=none}
> val empty : (abs, abs, abs) env
> 
> # let e1 = {empty with pear=some "Williams"}
> val e1 : (abs, abs, 'a) env
> # let e2 = {e1 with apple=some "Golden"; banana=some "Plantin"}
> val e2 : ('a, 'b, 'c) env
> 
> # let bar env s =
>     get env.pear ^ s
> val bar : ('a, 'b, pre) env -> string -> string
> # let foo env s =
>    bar env (get env.apple ^ get env.banana ^ s)
> val foo : (pre, pre, pre) env -> string -> string
> 
> # foo e2 "!";;
> - : string = "WilliamsGoldenPlantin!"
> 
> # foo e1;;
> This expression has type (Option.abs, Option.abs, 'a) env
> but is here used with type (Option.pre, Option.pre, Option.pre) env
> Type Option.abs = [ `abs | `pre ] is not compatible with type
>   Option.pre = [ `pre ]
> 
> Polymorphic variants are not essential here.
> They just allow one to forget about some fields of the environment
> without physically modifying it. For instance:
> 
> # let forget_pear env = (env :> (_,_,abs) env);;
> val forget_pear : ('a, 'b, [< abs ]) env -> ('a, 'b, abs) env
> 
> If you don't need this kind of operation, you could choose a simpler
> interface, which would be enough in most cases.
> module Option : sig
>   type (+'a,+'b) t
>   type abs
>   type pre
>   val none : ('a, abs) t
>   val some : 'a -> ('a, 'b) t
>   val get : ('a, pre) t -> 'a
> end
> 
> By the way, I had thought of a clever way to obtain nicer types:
> type 'u env =
>   {banana: (string, 'a) t; apple: (string, 'b) t; pear: (string, 'c) t}
>   constraint 'u = <banana:'a; apple:'b; pear:'c>
> But after fiddling with it I discovered a serious bug in the type
> checker. Please do not use constraints on type variables that do not
> appear in the type itself until this is solved. Sorry for the
> inconvenience.
> 
> Jacques Garrigue
> 
> 
> 
> _______________________________________________
> Caml-list mailing list. Subscription management:
> http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
> Archives: http://caml.inria.fr
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>


  reply	other threads:[~2004-12-09  6:02 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-12-09  2:07 HENRIKSON, JEFFREY
2004-12-09  4:47 ` [Caml-list] " Jacques Garrigue
2004-12-09  6:02   ` Michael Walter [this message]
2004-12-09 11:28     ` Jacques Garrigue
2004-12-09 20:02     ` pad
2004-12-09 23:11       ` Jacques Garrigue
2004-12-10  2:30         ` skaller
2004-12-09  9:09 ` Richard Jones
2004-12-09 13:12   ` [Caml-list] " Ville-Pertti Keinonen
2004-12-10 11:59     ` Richard Jones
2004-12-10 10:52 ` [Caml-list] " Andrej Bauer
2004-12-10 12:13   ` Richard Jones
2004-12-10 23:35     ` Jacques Garrigue
2004-12-11  2:30   ` skaller
2004-12-11 14:31     ` Andrej Bauer
2004-12-11 18:13       ` Markus Mottl
2004-12-11 23:56         ` skaller
2004-12-12  2:36           ` William Lovas
2004-12-12  5:33             ` skaller
2004-12-12 19:09               ` Michael Walter
2004-12-13  0:48                 ` skaller
2004-12-13  2:03                   ` Michael Walter
2004-12-13  2:05                     ` Michael Walter
     [not found]                       ` <877e9a170412121844b633bb8@mail.gmail.com>
2004-12-13  2:45                         ` Michael Walter
2004-12-13  6:18                           ` skaller
2004-12-13  7:08                             ` skaller
2004-12-13  9:56                             ` Michael Walter
2004-12-13 12:59                               ` skaller
2004-12-13  8:56                           ` Thomas Fischbacher
2004-12-13  9:21                             ` Jacques Garrigue
2004-12-13 10:05                               ` Michael Walter
2004-12-13 10:29                                 ` Thomas Fischbacher
2004-12-13 21:16                                   ` Michael Walter
2004-12-13 10:20                               ` Thomas Fischbacher
2004-12-13 12:09                                 ` Jacques Garrigue
2004-12-13 12:48                                   ` Thomas Fischbacher
2004-12-13 14:09                                   ` skaller
2004-12-13 21:39                                     ` Michael Walter
2004-12-13 13:22                                 ` skaller
2004-12-13 16:54                                   ` Marcin 'Qrczak' Kowalczyk
2004-12-13 18:44                                   ` Thomas Fischbacher
2004-12-13 10:11                             ` Michael Walter
2004-12-13 11:46                             ` skaller
2004-12-13  5:41                     ` skaller
2004-12-13  9:29                       ` Michael Walter
2004-12-13 12:30                         ` skaller
2004-12-13 13:49                           ` Martin Berger
2004-12-12 23:03           ` Thomas Fischbacher
2004-12-13  1:26             ` skaller
2004-12-13  8:37               ` Thomas Fischbacher
2004-12-13 10:53                 ` skaller
2004-12-13 11:38                   ` Martin Berger
2004-12-13 13:33                     ` skaller
2004-12-13 12:01                   ` Thomas Fischbacher
2004-12-13 13:41                     ` skaller
2004-12-11 23:29       ` skaller
2004-12-12  0:21         ` Jacques Carette

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=877e9a170412082202790e2cfb@mail.gmail.com \
    --to=michael.walter@gmail.com \
    --cc=JEFHEN@safeco.com \
    --cc=caml-list@inria.fr \
    --cc=garrigue@math.nagoya-u.ac.jp \
    /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