Version française
Home     About     Download     Resources     Contact us    
Browse thread
Type constraint to explain that a polymorphic variants is included into another
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Jacques Garrigue <garrigue@m...>
Subject: Re: [Caml-list] Type constraint to explain that a polymorphic variants is included into another
On 2010/10/09, at 2:13, Sylvain Le Gall wrote:

> Hello all,
> 
> I would like to build an interface for plugins that allow to extract at the
> same time a very specific data for a plugin family and to extract
> general help for plugins.
> 
> Here is an example:

[...]

> This code doesn't compile because I see no way to explain that F.kind is
> included into plugin_kind. 

I'm not sure of what you are trying to do, but private rows where introduced
with this goal in mind.

The idea is to change the abstract definition of kind in PLUGIN_FAMILY to

  type kind = private [< plugin_kind]

meaning that kind can be instantiated to any subset of plugin_kind.
You can then use subtyping to convert from kind to plugin_kind.

Here is a typable version of your code.
Note that I had to do a few other changes to make the types match.

Jacques

(** All the plugins I want to manage *)
type plugin_kind = [`Build | `Install]

(** Generic plugin *)
type 'a plugin = 'a * string

(** Help data for all plugin *)
module MapPlugin = 
 Map.Make
   (struct
      type t = plugin_kind plugin
      let compare = compare
    end)

let all_help: string MapPlugin.t ref = 
 ref MapPlugin.empty

let help plg = 
 MapPlugin.find plg !all_help

(** Functor to build function related to one type of plugin *)
module type PLUGIN_FAMILY = 
sig
 type act
 type kind = private [< plugin_kind]
 val kind_default: kind
end


module Make (F: PLUGIN_FAMILY) = 
struct

 module MapPluginSelf = 
   Map.Make
     (struct 
        type t = F.kind plugin
        let compare = compare
      end)

 let all_act: F.act MapPluginSelf.t ref = 
   ref MapPluginSelf.empty

 let act (plg : F.kind plugin) =
   MapPluginSelf.find plg !all_act

 let create name help act = 
   let id = 
     F.kind_default, name
   in
     all_help := MapPlugin.add (id :> plugin_kind * _) help !all_help;
     all_act  := MapPluginSelf.add id act !all_act;
     id
end

(** Functions for build plugins *)
module Build =
 Make
   (struct 
      type act = unit -> unit 
      type kind = [`Build]
      let kind_default = `Build
    end)

(** Functions for install plugins *)
module Install = 
 Make
   (struct 
      type act = string list -> unit
      type kind = [`Install]
      let kind_default = `Install
    end)

type package = 
   {
     name: string;
     plugin_build: [`Build] plugin;
     plugin_install: [`Install] plugin;
   }

let run pkg = 
 prerr_endline (help (pkg.plugin_build :> MapPlugin.key));
 prerr_endline (help (pkg.plugin_install :> MapPlugin.key));
 (Build.act pkg.plugin_build) ();
 Install.act pkg.plugin_install []