From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by yquem.inria.fr (Postfix) with ESMTP id A5F4BBC57 for ; Sat, 4 Sep 2010 12:18:47 +0200 (CEST) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AgYHAPK5gUzNm0EP/2dsb2JhbACTdAJ7iTeCdnG6J4U9BIRDhVSCfg X-IronPort-AV: E=Sophos;i="4.56,317,1280700000"; d="scan'208";a="58546330" Received: from virginia.nps.edu ([205.155.65.15]) by mail2-smtp-roc.national.inria.fr with ESMTP; 04 Sep 2010 12:18:46 +0200 Received: from Adric.ern.nps.edu ([172.20.216.170]) by virginia.nps.edu with Microsoft SMTPSVC(6.0.3790.4675); Sat, 4 Sep 2010 03:18:44 -0700 Received: by Adric.ern.nps.edu (Postfix, from userid 760) id 4798517415; Sat, 4 Sep 2010 03:17:58 -0700 (PDT) From: oleg@okmij.org To: sylvain@le-gall.net Cc: caml-list@inria.fr Subject: Re: Create a constraint between variant type and data list Message-Id: <20100904101758.4798517415@Adric.ern.nps.edu> Date: Sat, 4 Sep 2010 03:17:58 -0700 (PDT) X-OriginalArrivalTime: 04 Sep 2010 10:18:44.0364 (UTC) FILETIME=[8DE4E4C0:01CB4C1A] X-Spam: no; 0.00; oleg:01 lgpl:01 lgpl:01 variants:01 way':01 sig:01 val:01 val:01 struct:01 gcc:01 lics:01 printf:01 printf:01 lics:01 gpl:01 Sylvain Le Gall wrote: > I would like to define: > > type license = GPL | LGPL > > and > > let data = [ GPL, "GNU Public license"; > LGPL, "GNU Lesser General Public license" ] > > I would like to enforce that all variants of license are in the > association list. In other words, you would like a set of values of a distinct type, each of which is associated with a printable string. One should be able to add to the set in some `authorized way'; one should not be able to make a value of that distinct type in an unauthorized way (that is, by accident). Right? It seems the following solution then would satisfy the specification: module LICENSE : sig type t val print_lic : t -> string val gpl : t val lgpl : t (* more can be added *) end = struct type t = string let print_lic x = x let gpl = "GNU Public license" let lgpl = "GNU Lesser General Public license" end;; (* Usage example *) type package = {pkg_name : string; pkg_lic : LICENSE.t};; let packages = [{pkg_name = "gcc"; pkg_lic = LICENSE.gpl}; {pkg_name = "lgpled"; pkg_lic = LICENSE.lgpl}] ;; let rec pr_lics = function [] -> () | {pkg_lic = l}::t -> Printf.printf "%s\n" (LICENSE.print_lic l); pr_lics t ;; let rec all_of_lic l = function [] -> [] | {pkg_name = name; pkg_lic = l'}::t when l' == l -> name :: all_of_lic l t | _::t -> all_of_lic l t ;; all_of_lic LICENSE.lgpl packages;; One can't overlook specifying the description string. One can't create new values of the type LICENSE.t `by accident' (the only possible values of the type are the ones exported by the module).