caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Anton Bachin <antronbachin@gmail.com>
To: "caml-list@inria.fr users" <caml-list@inria.fr>
Subject: [Caml-list] GADT+polymorphic variants quirk
Date: Tue, 27 Dec 2016 14:04:59 -0600	[thread overview]
Message-ID: <B2CFF70E-5424-48DE-9DC7-6E9F36259B60@gmail.com> (raw)

Hello,

Consider this code for simulating an ad-hoc polymorphic addition
function:

    type whole = [ `Integer ]
    type general = [ whole | `Float ]

    type _ num =
      | I : int -> [> whole ] num
      | F : float -> general num

    module M :
    sig
      val add : ([< general ] as 'a) num -> 'a num -> 'a num
      val to_int : whole num -> int
      val to_float : general num -> float
    end =
    struct
      let add : type a. a num -> a num -> a num = fun a b ->
        match a, b with
        | I n, I m -> I (n + m)
        | F n, I m -> F (n +. float_of_int m)
        | F n, F m -> F (n +. m)
        | _ ->
          (* ----NOTE---- *)
          match b, a with
          | F m, I n -> F (float_of_int n +. m)
          | _ -> assert false

      let to_int : whole num -> int = fun (I n) -> n

      let to_float = function
        | I n -> float_of_int n
        | F n -> n
    end

    let () =
      M.add (I 1) (I 2)  |> M.to_int   |> Printf.printf "%i\n";
      M.add (I 1) (F 2.) |> M.to_float |> Printf.printf "%f\n"

Instead of the nested match expression (marked with (* NOTE *)), I would
have expected to just write

    | I n, F m -> ...

However, if I actually do that, the result is an error on the expression
in the case:

    Error: This expression has type general num
           but an expression was expected of type a num
           Type general = [ `Float | `Integer ] is not compatible with type
             a = [> `Integer ] 
           The second variant type does not allow tag(s) `Float

While the reversed case type-checks successfully. I can imagine why this
would be so, but I want to ask the experts on the mailing list.

Is this a known quirk of the typechecker? A bug? Is there some
alternative syntax I am missing that would allow the I n pattern to be
written first?

Note that there is a way to rewrite the nested match cases to avoid _
and maintain the exhaustiveness check. I wrote them out as above for
clarity. The actual solution I have settled on for now is:

      let add : type a. a num -> a num -> a num = fun a b ->
        match a, b with
        | I n, I m -> I (n + m)
        | F n, I m -> F (n +. float_of_int m)
        | _,   F m ->
          match a with
          | I n -> F (float_of_int n +. m)
          | F n -> F (n +. m)

Best,
Anton


P.S. If interested, the code was for this Stack Overflow question:

    http://stackoverflow.com/questions/41214000

answer:

    http://stackoverflow.com/a/41334879/2482998


             reply	other threads:[~2016-12-27 20:05 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-12-27 20:04 Anton Bachin [this message]
2017-01-02 13:51 ` Jacques Garrigue
2017-01-03 14:05 Nils Becker
2017-01-03 15:09 ` Anton Bachin
2017-01-03 15:22   ` Anton Bachin
2017-01-06  1:39 ` Jacques Garrigue

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=B2CFF70E-5424-48DE-9DC7-6E9F36259B60@gmail.com \
    --to=antronbachin@gmail.com \
    --cc=caml-list@inria.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).