From : Jacques Garrigue <garrigue AT math.nagoya-u.ac.jp>

: Jacques Garrigue <garrigue AT math.nagoya-u.ac.jp> To : OCaml List <caml-list AT inria.fr>

: OCaml List <caml-list AT inria.fr> Subject : [Caml-list] Propagating types to pattern-matching

: [Caml-list] Propagating types to pattern-matching Date : Tue, 15 Jan 2013 14:59:34 +0900

: Tue, 15 Jan 2013 14:59:34 +0900 Domainkey-signature: h=Received:From:Content-Type:Content-Transfer-Encoding:Subject:Date:To:Message-Id:Mime-Version:X-Mailer; b=; c=nofws; d=math.nagoya-u.ac.jp; q=; s=alpha

[Caml-list] Propagating types to pattern-matching, Jacques Garrigue, 01/15/2013

Dear Camlers,It is a bit unusual, but this message is about changes in trunk.As you may be aware from past threads, since the introduction of GADTsin 4.00, some type information is propagated to pattern-matching, to allowit to refine types.More recently, types have started being used to disambiguate constructorsand record fields, which means some more dependency on type informationin pattern-matching.However, a weakness of this approach was that propagation was disabledas soon as a pattern contained polymorphic variants. The reason is thattyping rules for polymorphic variants in patterns and expression are subtlydifferent, and mixing information without care would lose principality.At long last I have removed this restriction on the presence of polymorphicvariants, but this has some consequences on typing:* while type information is now propagated, information about possiblypresent constructors still has to be discarded. For instance this means thatthe following code will not be typed as you could expect:let f (x : [< `A | `B]) = match x with `A -> 1 | _ -> 2;;val f : [< `A | `B > `A ] -> intWhat happens is that inside pattern-matching, only required constructorsare propagated, which reduces the type of x to [> ] (a polymorphic varianttype with any constructor…)As before, to give an upper bound to the matched type, the type annotationmust be inside a pattern:let f = function (`A : [< `A | `B]) -> 1 | _ -> 2;;val f : [< `A | `B ] -> int = * the propagation of type information may lead to failure in some cases thatwhere typable before:type ab = [ `A | `B ];;let f (x : [`A]) = match x with #ab -> 1;;Error: This pattern matches values of type [? `A | `B ]but a pattern was expected which matches values of type [ `A ]The second variant type does not allow tag(s) `BDuring pattern-matching it is not allowed to match on absent typeconstructors,even though the type of the patterns would eventually be [< `A | `B], whichallowsdiscarding `B. ([? `A | `B] denotes a type obeying the rules ofpattern-matching)* for the sake of coherence, even if a type was not propagated because itwas not known when typing a pattern-matching, we are still going to fail ifmatched constructor appears to be absent after typing the whole function.(This only applies to propagable types, i.e. polymorphic variant types thatcontain only required constructors)In particular the last two points are important, because previously such useswould not have triggered even a warning.The idea is that allowing propagation of types is more important thankeeping some not really useful corner cases, but if this is of concernto you, I'm interested in feedback.Jacques Garrigue