Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0004998OCamlOCaml generalpublic2010-03-10 16:452011-06-01 17:06
Reportergoswin 
Assigned To 
PrioritynormalSeverityfeatureReproducibilityalways
StatusacknowledgedResolutionopen 
PlatformOSOS Version
Product Version 
Target VersionFixed in Version 
Summary0004998: Feature request: Sub/Supersets of non-polymorphic variants
DescriptionI find myself in a position where I have to store number of items in a tree structure. So I defined a variant type covering all the items. In other places of the code, where I use the items, I know that only a limited set of items can ever occur or must only occur. Other items can or may not occur.

With a non-polymorphic variant type I have no way to reflecting that fact in the type of values and then I need to match cases I know can/must not happen or suffer lots of warnings.

On the other hand polymorphic variants use more memory and my tree will be HUGE so that is a real concern. Polymorphic variants also require type annotations to close the type and to get the strict typechecks like non-polymorphic variants.


Consider the following polymorphic variant:

# type 'a t = 'a constraint 'a = [ `A | `B | `C ];;
type 'a t = 'a constraint 'a = [ `A | `B | `C ]

# let f = function `A -> `B | (x : [< 'a t]) -> x;;
val f : ([< [ `A | `B | `C ] t > `B ] as 'a) -> 'a = <fun>

# let x = (`A : [`A | `B]);;
val x : [ `A | `B ] = `A

# let y = match f x with `A -> "A" | `B -> "B";;
val y : string = "B"

# let z = match x with `A -> "A";;
Error: This pattern matches values of type [< `A ]
       but a pattern was expected which matches values of type [ `A | `B ]
       The first variant type does not allow tag(s) `B


And now contrast that with the non-polymorphic type

# type t = A | B | C;;
type t = A | B | C

# let f = function A -> B | x -> x;;
val f : t -> t = <fun>

# let x = A;;
val x : t = A

# let y = match f x with A -> "A" | B -> "B";;
Warning P: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
C
val y : string = "B"

# let z = match x with A -> "A";;
Warning P: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
(C|B)
val z : string = "A"


Wouldn't it be great if one could declare a subset of the variant type:

let x = (A : [A | B]);;

Then the warning for y could be avoided as the type system would know that C will never happen. Also for z it could produce an error same as for the polymorphic variant example.

I do not ask for the existing behaviour of non-polymorphic variants to change. The sub/supersets should only be given explicitly and not infered like polymorphic variants. So example below should still give that warning unlike g.

# let f = function A -> "A" | B -> "B";;
Warning P: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
C
val f : t -> string = <fun>

# let g = function `A -> "A" | `B -> "B";;
val g : [< `A | `B ] -> string = <fun>

Also non-polymorphic variants would always be limited to be a subset of the full type. One could not write:

# type s = D let f = function A -> "A" | B -> "B" | C -> "C" | D -> "D";;
Error: This pattern matches values of type s
       but a pattern was expected which matches values of type t

MfG
   Goswin
TagsNo tags attached.
Attached Files

- Relationships

-  Notes
(0005950)
doligez (administrator)
2011-06-01 17:06

If only we knew how to do that...

- Issue History
Date Modified Username Field Change
2010-03-10 16:45 goswin New Issue
2011-06-01 17:06 doligez Note Added: 0005950
2011-06-01 17:06 doligez Status new => acknowledged


Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker