--- In ocaml_beginners@yahoogroups.com, Jon Harrop <jon@...> wrote:
>
> On Monday 29 June 2009 14:57:43 Vincent Aravantinos wrote:
> > 1) either I define the type as private, ie.
> > module M :
> > sig
> > type t = private A of a | B of b | C of c
> > ...
> > end
> > in which case I can still destructure the data from the outside; but I
> > don't really like this solution as it still reveals some part of the
> > implementation.
>
> Yes. That solutions works well when it is suitable. Specifically, when the
> arguments of the type constructors can all be public and do not reflect
> implementation details.
Exactly. I could not manage to express it as clear...
> > 2) or I keep the type completely abstract and define the following function
> > : let destruct (case_a : a -> 'a) (case_b: b -> 'a) (case_c : c -> 'a) =
> > function
> >
> > |A(a) -> case_a a
> > |B(b) -> case_b b
> > |C(c) -> case_c c
> >
> > which completely hides the structure but is absolutely not handy.
>
> Yes. Assuming you mean a higher-order function that accepts "case_a" etc. in
> the general case then this is cumbersome because you're reduced to Lisp-style
> coding and cannot leverage pattern matching.
Exactly. That's the solution I first chose, this is of course very general but
we lose all the advantages of pattern matching (we cannot make guards nor
factorise cases). Furthermore the strict semantics of ocaml imposes that the
parameters are evaluated before the call, i.e. case_a, case_b, case_c will be
first evaluated indepently of the case that will be really considered. With
functions that's not real problem but for values this can be quite annoying,
leading to big inefficencies, or even worse in the case of my app, to
non-termination... Adding some artificial unit types to force evaluation order
does the trick but turns the code into a real mess.
> > 3) I was also thinking of defining a front type e.g.
> > module M :
> > sig
> > type t = private A of a | B of b | C of c
> > ...
> > end
> > =
> > struct
> > type t = private A of a | B of b | C of c (* supposed no to change *)
> > type t' = A' of a' | ... (* may change *)
> > let t_to_t' = ...
> > let t'_to_t = ...
> > end
>
> That is essentially a manual implementation of views (aka "active patterns" in
> F#). They are very powerful and particularly useful in the context of
> dressing up alien data structures (e.g. the .NET representation of XML trees
> in F# so they can be destructured using pattern matching). I also use them
> extensively in F# for Visualization to wrap WPF code in an elegant functional
> API.
Great, I didn't know what was "views" ! The problem I see in my "manual
implementation" is that it imposes to make frequent conversions from one data to
another.
Views allow to keep the syntactic pleasant aspect of pattern matching while not
having to maintain an artificial data structure, am I right ?
> There is an OCaml implementations of views that automates the tediousness.
Is it micmatch ?
> Depends entirely upon the specifics of what you're doing. You have described
> several techniques that I have found to be applicable in different
> circumstances. In general, I suggest you start by making the exposing the
> variant type but making its constructors accept arguments of abstract types.
Ok. I finally stuck to private types but I will give a try to views.
At least I know now that those questions have some sense :-)
Thanks a lot,
--
Vincent Aravantinos
PhD Student - LIG - CAPP Team
Grenoble, France
+33.6.11.23.34.72
vincent.aravantinos@...
http://membres-lig.imag.fr/aravantinos/