« Return to Thread: "ocaml_beginners"::[] De-unifying variant types

"ocaml_beginners"::[] De-unifying variant types

by cultural_sublimation :: Rate this Message:

Reply to Author | View in Thread

Hi,

Here's the situation:  I am building a small module to encapsulate the
nasty type-unsafe task of extracting data stored in a Postgresql database.
(I am using the postgresql-ocaml bindings by Markus Mottl to connect
to Postgresql).

For simplicity sake, let us assume there are only two tables in
the database: "movies" (containing 3 fields: title, year, and B&W,
respectively of types text, integer, and boolean), and "actors"
(containing 2 fields: name and age, of text and integer types).

Now, as far as I can tell, regardless of the Postgresql datatypes, any
row resulting from a SELECT statement will be seen by the Ocaml program
as a "string array".  Therefore, I have made two simple functions that
convert the "string array" into proper tuples of movies and actors:


  type movie_t = string * int * bool
  type actor_t = string * int
  type query_result = Movie of movie_t | Actor of actor_t

  let array_to_movie a = Movie (a.(0), int_of_string a.(1),
bool_of_string a.(2))
  let array_to_actor a = Actor (a.(0), int_of_string a.(2))


The reason why the movie_t and actor_t were unified under that
"query_result" variant is because there is a "process_query" function
which should accept results based both on movies or actors:


  let process_query array_converter converter_template result =
      let size = Array.length result in
      let converted = Array.make size converter_template in
      for i = 0 to size-1 do
          converted.(i) <- array_converter (result.(i))
      done;
      converted


Now, all of the these functions are fairly low-level and are not meant
to be used
directly by the users of the module.  Instead, the user should handle
all tasks
via two other functions, process_movies and process_actors, as follows:


  let process_movies result =
      let converter_template = Movie ("", 0, false) in
      process_query array_to_movie converter_template result

  let process_actors result =
      let converter_template = Actor ("", 0) in
      process_query array_to_actor converter_template result


This is all fine and dandy, except that because of the unification,
the signature of both process_movies and process_actors is the same:


  val process_movies : string array array -> query_result array
  val process_actors : string array array -> query_result array


My question is the following: how do I undo the unification of movie_t
and actor_t, so that externally, the signatures of these functions are
different? (listed below).  I don't want the caller to be bothering
with matches, and quite frankly, the fact that movie_t and actor_t were
unified is an implementation detail, used only to avoid the duplication
of the process_query code.


  val process_movies : string array array -> movie_t array
  val process_actors : string array array -> actor_t array


Thanks a lot for your help!!
Cheers,
C.S.



 « Return to Thread: "ocaml_beginners"::[] De-unifying variant types