Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: Sub/Supersets of non-polymorphic variants #4998

Closed
vicuna opened this issue Mar 10, 2010 · 2 comments
Closed

Feature request: Sub/Supersets of non-polymorphic variants #4998

vicuna opened this issue Mar 10, 2010 · 2 comments

Comments

@vicuna
Copy link

vicuna commented Mar 10, 2010

Original bug ID: 4998
Reporter: goswin
Status: acknowledged (set by @damiendoligez on 2011-06-01T15:06:31Z)
Resolution: open
Priority: normal
Severity: feature
Category: typing
Monitored by: @hcarty

Bug description

I 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

@vicuna
Copy link
Author

vicuna commented Jun 1, 2011

Comment author: @damiendoligez

If only we knew how to do that...

@github-actions
Copy link

This issue has been open one year with no activity. Consequently, it is being marked with the "stale" label. What this means is that the issue will be automatically closed in 30 days unless more comments are added or the "stale" label is removed. Comments that provide new information on the issue are especially welcome: is it still reproducible? did it appear in other contexts? how critical is it? etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant