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 4BA817EFCD for ; Sat, 4 Oct 2014 17:23:44 +0200 (CEST) Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of gabriel.scherer@gmail.com) identity=pra; client-ip=209.85.218.51; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="gabriel.scherer@gmail.com"; x-sender="gabriel.scherer@gmail.com"; x-conformance=sidf_compatible Received-SPF: Pass (mail2-smtp-roc.national.inria.fr: domain of gabriel.scherer@gmail.com designates 209.85.218.51 as permitted sender) identity=mailfrom; client-ip=209.85.218.51; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="gabriel.scherer@gmail.com"; x-sender="gabriel.scherer@gmail.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@mail-oi0-f51.google.com) identity=helo; client-ip=209.85.218.51; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="gabriel.scherer@gmail.com"; x-sender="postmaster@mail-oi0-f51.google.com"; x-conformance=sidf_compatible X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AjIBACoQMFTRVdozm2dsb2JhbABgg2FYBIJ+twuRH4dJAn4IFgERAQEBAQEGCwsJFCyEBAEBBBIRBBkBGxILAQMMBgULDQICCR0CAiEBAREBBQEKEgYTEhCIBwEDEQ2dK26LMIFygxCISgoZJwMKZ4YxAREBBQ6BHoxoHYIUB4J3gVQBBIUVBY1ggzaEfYIRgS07jUeCUoINGCmFFjsvBYEDJIEeAQEB X-IPAS-Result: AjIBACoQMFTRVdozm2dsb2JhbABgg2FYBIJ+twuRH4dJAn4IFgERAQEBAQEGCwsJFCyEBAEBBBIRBBkBGxILAQMMBgULDQICCR0CAiEBAREBBQEKEgYTEhCIBwEDEQ2dK26LMIFygxCISgoZJwMKZ4YxAREBBQ6BHoxoHYIUB4J3gVQBBIUVBY1ggzaEfYIRgS07jUeCUoINGCmFFjsvBYEDJIEeAQEB X-IronPort-AV: E=Sophos;i="5.04,653,1406584800"; d="scan'208";a="99386146" Received: from mail-oi0-f51.google.com ([209.85.218.51]) by mail2-smtp-roc.national.inria.fr with ESMTP/TLS/RC4-SHA; 04 Oct 2014 17:23:43 +0200 Received: by mail-oi0-f51.google.com with SMTP id e131so2000905oig.10 for ; Sat, 04 Oct 2014 08:23:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type; bh=AJr0Cpy5PpiQYhTYAoEEJhcfK2zauvPZgo3JP+Q2LBc=; b=AI/LlRQgn8rv4MO8pGhKOc2TXwiLfJbEoFTsbtUCWXQzmbrgtD0HaML+hALNJTkSWD fh969Srnj9fzTtN6RUoFCt92Hb5V2VLGViLHuAf4J9HcE4WtkxgLZujsJDh7IHUlcx9L azjoV2LRRnYb86Y+1E+rARXzU3kaPTtqI8MWkkX+Aa1on7lQu9YjXyZVqjiQTOCODPlB HFo7C+62azvQM6BxOTXCEBbvHKJFvhFc20esYxE+W4vdFnErE2XyMkvaSBSsrvx2xfkt 6jm7xM7fvragpE/IS6z6JTskt4vYo6kCW9IW3bTfXPk7iWPswUGg8ftzUHB/XmykrsvI Wbug== X-Received: by 10.182.126.162 with SMTP id mz2mr14822797obb.19.1412436222060; Sat, 04 Oct 2014 08:23:42 -0700 (PDT) MIME-Version: 1.0 Received: by 10.76.105.196 with HTTP; Sat, 4 Oct 2014 08:23:02 -0700 (PDT) In-Reply-To: <20141004165458.4efce446@xivilization.net> References: <20141004150511.7e8de126@xivilization.net> <87a95cklck.fsf@gmail.com> <20141004165458.4efce446@xivilization.net> From: Gabriel Scherer Date: Sat, 4 Oct 2014 17:23:02 +0200 Message-ID: To: Marek Kubica Cc: Malcolm Matalka , Caml List Content-Type: text/plain; charset=UTF-8 Subject: Re: [Caml-list] [ANN] slacko-0.9.0 Re. the "validate" function, you can do it using the ability to pattern-match on a named subset of the polymorphic variants. Let's consider a simplification of your problem with only two classes of errors (taken from your code): type error_cant_kick = [ | `Cant_kick_from_general | `Cant_kick_from_last_channel | `Cant_kick_self ] type error_cant_invite = [ | `Cant_invite | `Cant_invite_self ] type 'a error = [ | `Success of 'a | error_cant_kick | error_cant_invite ] The `validate` function indeed processes all cases, returning an everything-possible error type: let validate : _ -> _ error = function | `String "cant_invite_self" -> `Cant_invite_self | `String "cant_invite" -> `Cant_invite | `String "cant_kick_self" -> `Cant_kick_self | `String "cant_kick_from_general" -> `Cant_kick_from_general | `String "cant_kick_from_last_channel" -> `Cant_kick_from_last_channel But you can refine its result if you know (from the informal API specification) that it can only be some subset, using the #foo syntax. In the example below, `kick` and `invite` have been refined with distinct subsets: let api_mismatch err = failwith ("API mismatch: unexpected error " (*^ to_string err *)) let kick f = f () |> validate |> function | `Success v -> `Success v | #error_cant_kick as err -> err | other -> api_mismatch other let invite f = f () |> validate |> function | `Success v -> `Success v | #error_cant_invite as err -> err | other -> api_mismatch other `kick` now returns a [> error_cant_kick | `Success of 'a ], while `invite` returns [> error_cant_invite | `Success of 'a ]. On Sat, Oct 4, 2014 at 4:54 PM, Marek Kubica wrote: > Hello Malcolm, > > Thanks for looking into my code. > > On Sat, 04 Oct 2014 13:36:43 +0000 > Malcolm Matalka wrote: > >> I would either change the 'apierror' type to normal variants, or >> spread out the apierror to multiple types. Can every API function >> really return every one of those errors? The value of polymorphic >> variants is they are module, and you can share the constructors >> across types. > > You're right, there is a common set of errors that most functions return > and then there are some specific errors. > > Originally I didn't want to create such a huge type but have every > function have its own polymorphic variants that apply to it, so users > of the API know exactly what errors might be thrown and have to handle > these. The huge type is a direct result of the "validate" function > > which tests all cases. > > I tried specifying a smaller subset of polymorphic variants, but the > compiler always selected the full set. I don't know how to fix this, > because on the one hand side I don't want to have a big monolithic > error type but on the other hand, I don't want to duplicate a subset of > the validate function in every function. > > Looking forward for ideas on how to solve this in a more elegant way. > >> I would also structure the API calls in terms of the Result.t type in >> Core. Right now success is part of the error type. > > If I understand you correctly, this should do the trick with the > current code: > > type result = Success of Yojson.Basic.json | Error of apierror > > For future releases I plan to replace the strings in the signatures > with proper types (so, some "string" turn into a "token" types, others > into timestamp types) and to process the resulting JSON into some more > convenient data structures. But for now, I hope to get the error > handling right and then build upon this. > > Thanks in advance! > > regards, > Marek > > -- > Caml-list mailing list. Subscription management and archives: > https://sympa.inria.fr/sympa/arc/caml-list > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > Bug reports: http://caml.inria.fr/bin/caml-bugs