English version
Accueil     À propos     Téléchargement     Ressources     Contactez-nous    

Ce site est rarement mis à jour. Pour les informations les plus récentes, rendez-vous sur le nouveau site OCaml à l'adresse ocaml.org.

Browse thread
wrapping parameterized types
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: 2007-05-03 (22:31)
From: Christopher L Conway <cconway@c...>
Subject: wrapping parameterized types
I recently ran across a rather surprising behavior in the OCaml type
system. I hope somebody may be able to advise me how to work around it
(or at least explain to me why things are the way they are!).

Suppose I want to pass around a restricted, un-parameterized list type:

# type mylist = Intlist of int list | Strlist of string list ;;
type mylist = Intlist of int list | Strlist of string list

Now I end up doing a lot of tedious case splits, like:

# let length_of_mylist = function Intlist x -> List.length x | Strlist
x -> List.length x ;;
val length_of_mylist : mylist -> int = <fun>

What one would like is something like "app_to_mylist : ('a list -> 'b)
-> mylist -> 'b" so one could write "app_to_mylist List.length", but:

# let app_to_mylist f = function Intlist x -> f x | Strlist x -> f x ;;
Characters 65-66:
  let app_to_mylist f = function Intlist x -> f x | Strlist x -> f x ;;
This expression has type string list but is here used with type int list

The solution I've tripped over is to pass in separate functions for
the different cases, and then (only somewhat less tediously than
above) duplicate the same function at the call site:

# let app_to_mylist (fi,fs) = function Intlist x -> fi x | Strlist x -> fs x ;;
val app_to_mylist : (int list -> 'a) * (string list -> 'a) -> mylist -> 'a =
# let length_of_mylist = app_to_mylist (List.length, List.length);;
val length_of_mylist : mylist -> int = <fun>

I can't help but feel there is a more elegant way to handle this,
perhaps drawing in objects or functors. Any suggestions?

This question arises from an attempt to use the APRON library, which
provides types parameterized by numerical domain, alongside other
numerical tools in a uniform way---the APRON interface deals with the
parameterized types generically, but I need to hoist the abstraction
up one layer and deal with both APRON and non-APRON types generically.
The details are far too ugly to wade into here...