Wildcard pattern overriding subtype constraint on polymorphic variant

允我心安 提交于 2019-12-05 07:20:13

The underlying question is why the type of

let pp= function
| `A -> "A"
| `B -> "B"
| _ -> "?"

is infered as [> `A| `B] -> string and not as [< `A| `B | ... ] -> string (where ... stands for any constructor). The answer is that is a design choice and a question of compromise between false positive and false negative : https://www.math.nagoya-u.ac.jp/~garrigue/papers/matching.pdf .

More precisely, the second type was deemed too weak since it was too easy to lose the information that `A and `B were present in pp. For instance, consider the following code where `b is a spelling mistake and should have been `B:

let restrict (`A | `b) = ()
let dual x = restrict x, pp x

Currently, this code fails with

Error: This expression has type [< `A | `b] but an expression was expected of type [> `A | `B ]
The first variant type does not allow tag(s) `B

At this point, if `b was a spelling mistake, it becomes possible to catch the mistake here. If pp had been typed [< `A|`B |..], the type of dual would have been restricted to [`A] -> unit * string silently, with no chance of catching this mistake. Moreover, with the current typing, if `b was not a spelling mistake, it is perfectly possible to make dual valid by adding some coercions

let dual x = restrict x, pp (x:[`A]:>[>`A]);;
(* or *)
let dual x = restrict x, (pp:>[`A] -> _) x

making it very explicit that restrict and pp works on different sets of polymorphic variants.

The type of the second version of pp is [< b > `A `B ] -> string. In other words, `A and `B must appear in the type. I guess it seems reasonable that if you want to compare a value against `B then `B should appear in the type of the value.

You can write pp (a :> b).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!