Version française
Home     About     Download     Resources     Contact us    
Browse thread
[Caml-list] Design advice
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: John Prevost <j.prevost@c...>
Subject: Re: [Caml-list] Design advice
>>>>> "ds" == Dan Schmidt <dfan@dfan.org> writes:

    ds> {...} it seems weird to perform
    ds> pattern matching on values that really have no semantic
    ds> importance other than the fact that they are different from
    ds> each other.  It's not like I'm going to have any code that
    ds> does one thing when given the 3 of Spades and another thing
    ds> when given the 3 of Hearts.  The other issue is that it is
    ds> mildly annoying to, for example, write a compare function to
    ds> be used inside a struct that implements the OrderedType
    ds> signature (e.g., if I want to have a Set of cards).

Well, note that in the type you've defined, the only thing in the type
is the different suits.  That is the *only* information there.  I
don't see why it seems unreasonable to pattern match here.

Note that the built-in comparison operations work just fine on types
defined this way.

    ds> {... similar angst about Player_One and Player_Two ...}

In this case, it only makes sense in games with precisely two players.
For example: Go, or Chess.  If you think you might be using an array
that you want to index into, you may very well be thinking of a game
with unbounded numbers of players--or a library for unbounded numbers
of players.  (For example, Bridge has only four players, but a more
general library for hands of cards might support an arbitrary number.)

In the case of a set number of players, you might use a tuple instead
of an array, since you know the precise size, and you know which
player goes with which item.  As an example:

type player = North | South | East | West
type state = { n_hand : hand, s_hand : hand, e_hand : hand, w_hand : hand }

let get_hand p st = match p with
  | North -> st.n_hand
  | South -> st.s_hand
  | East -> st.e_hand
  | West -> st.w_hand

Is this a little heavy?  Well, possibly.  But it's not unreasonable,
and it does at the very least restrict possible "unsafe" operations to
certain sections of code.  You might, for example, do this instead of
the above:

type player = (* same *)
type state = hand array

let player_to_index = function
  | North -> 0
  | South -> 1
  | East -> 2
  | West -> 3

let get_hand p st = st.(player_to_index p)

And don't export player_to_index or the structure of the state type.
Now the "unsafe" region of your code is just in the library that
contains the above.  Anything that uses it manipulates things purely
in terms of the bounded type, and you only have to verify that
indexing works right in the above library.

When in doubt, export the safest interface possible and then ensure
that your module's internals are correct.  That way you have at least
ensured that users of your module cannot feed you bad arguments.

    ds> Finally, is there any type in the library that functions like
    ds> an immutable array?  I would like to have an indexable bunch
    ds> of values but use it in a purely functional way.  I could
    ds> always just use Arrays and copy them before updating, but if
    ds> there's already an idiomatic type to use I'd prefer to use
    ds> that.

There is none in the base O'Caml.  But this might be more efficient
than copying all the time:

http://www.ai.univie.ac.at/~markus/home/ocaml_sources.html

Take a look in 4.1.6 (Okasaki's Purely Functional Datastructures in
OCaml), chp9.ml, and look at the random access lists.
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners