From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@sympa.inria.fr Delivered-To: caml-list@sympa.inria.fr Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by sympa.inria.fr (Postfix) with ESMTPS id 98C467ED25 for ; Thu, 18 Jul 2013 16:01:42 +0200 (CEST) Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of dra-news@metastack.com) identity=pra; client-ip=81.103.221.47; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="dra-news@metastack.com"; x-sender="dra-news@metastack.com"; x-conformance=sidf_compatible Received-SPF: Neutral (mail2-smtp-roc.national.inria.fr: domain of dra-news@metastack.com does not assert whether or not 81.103.221.47 is permitted sender) identity=mailfrom; client-ip=81.103.221.47; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="dra-news@metastack.com"; x-sender="dra-news@metastack.com"; x-conformance=sidf_compatible; x-record-type="v=spf1" Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of postmaster@mtaout01-winn.ispmail.ntl.com) identity=helo; client-ip=81.103.221.47; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="dra-news@metastack.com"; x-sender="postmaster@mtaout01-winn.ispmail.ntl.com"; x-conformance=sidf_compatible X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AvEAAGDz51FRZ90vlGdsb2JhbABaxVwWDgEBAQEHDQkJFAMlgisIAh0BEkwFFlIjHAEEHgWIBJVWoEmUEgOOfZ1A X-IPAS-Result: AvEAAGDz51FRZ90vlGdsb2JhbABaxVwWDgEBAQEHDQkJFAMlgisIAh0BEkwFFlIjHAEEHgWIBJVWoEmUEgOOfZ1A X-IronPort-AV: E=Sophos;i="4.89,694,1367964000"; d="scan'208";a="26487240" Received: from mtaout01-winn.ispmail.ntl.com ([81.103.221.47]) by mail2-smtp-roc.national.inria.fr with ESMTP; 18 Jul 2013 16:01:41 +0200 Received: from aamtaout02-winn.ispmail.ntl.com ([81.103.221.35]) by mtaout01-winn.ispmail.ntl.com (InterMail vM.7.08.04.00 201-2186-134-20080326) with ESMTP id <20130718140141.UIRQ4711.mtaout01-winn.ispmail.ntl.com@aamtaout02-winn.ispmail.ntl.com> for ; Thu, 18 Jul 2013 15:01:41 +0100 Received: from romulus.metastack.com ([81.102.132.77]) by aamtaout02-winn.ispmail.ntl.com (InterMail vG.3.00.04.00 201-2196-133-20080908) with ESMTP id <20130718140140.TQTA6472.aamtaout02-winn.ispmail.ntl.com@romulus.metastack.com> for ; Thu, 18 Jul 2013 15:01:40 +0100 Received: from Altus ([213.205.229.23]) (authenticated bits=0) by romulus.metastack.com (8.14.2/8.14.2) with ESMTP id r6IE1a8m027511 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NO) for ; Thu, 18 Jul 2013 15:01:38 +0100 From: "David Allsopp" To: "OCaml List" Date: Thu, 18 Jul 2013 15:03:05 +0100 Organization: MetaStack Solutions Ltd. Message-ID: <000001ce83bf$879e6520$96db2f60$@metastack.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Mailer: Microsoft Outlook 14.0 Thread-Index: Ac6Dvpb+WbS2X7LISNO32SrC2vIKLg== Content-Language: en-gb X-Scanned-By: MIMEDefang 2.65 on 172.16.0.20 X-Cloudmark-Analysis: v=1.1 cv=GaEGOwq9FwezmTggA+b6yC6zDZF2HYaK6RN/tSqdnVA= c=1 sm=0 a=cTs9vV391PwA:10 a=RQQLJnld3ZcA:10 a=kj9zAlcOel0A:10 a=v8QqFCEBbuhyrvlFXSEA:9 a=CjuIK1q_8ugA:10 a=HpAAvcLHHh0Zw7uRqdWCyQ==:117 Subject: [Caml-list] GADT in an optional parameter So, continuing my forays into sections of type theory I clearly don't properly understand! Although I was trying to use it for something else, my problem here is equivalent to a rather over-discussed problem on this list - namely, raising exceptions vs wrapping results in 'a option I defined the following GADT: type ('a, 'b) wrap = Option : ('a, 'a option) wrap | Exn : ('a, 'a) wrap I then created the following alternate implementation of Map where find takes that GADT as its first parameter: module StringMap = struct include Map.Make(String) let find : type s t . (s, t) wrap -> string -> s Map.Make(String).t -> t = fun mode key map -> match mode with Exn -> find key map | Option -> try Some (find key map) with Not_found -> None end So far so good, as we can have: StringMap.find Option "foo" StringMap.empty;; (* None *) StringMap.find Exn "foo" StringMap.empty;; (* Not_found raised *) which is quite nice (ignoring any quite optimisable and probably negligible overhead of the extra match clause verses having two functions find and find_option). I then wanted to try to make the first parameter optional, defaulting to Exn (so you'd get the vanilla behaviour of Map.find): module StringMap = struct include Map.Make(String) let find : type s t . ?mode:(s, t) wrap -> string -> s Map.Make(String).t -> t = fun ?(mode = Exn) key map -> match mode with Exn -> find key map | Option -> try Some (find key map) with Not_found -> None end But I get: This expression has type (s, s) wrap but an expression was expected of type (s, t) wrap on the Exn default value. Now, in my woolly way, I thought that the default value for an optional parameter behaved /almost/ like syntactic sugar, but clearly not. Is there a way to annotate this to achieve what I'm after? David