多态变体子类型实现与签名不匹配
Polymorphic variant subtype implementation does not match signature
我有以下代码:
module Test : sig
type +'a t
val make : int -> [< `a | `b] t
end = struct
type 'a t = Foo of int | Bar of string
let make = function
| 0 -> (Foo 0 : [`a] t)
| _ -> (Bar "hi" : [`a] t)
end
您可能会注意到,抽象类型 'a t
在其类型参数 'a
中被声明为协变的,并且 make
构造函数被声明为 returning 子类型 的多态变体案例 a
或 b
.
在我的 make
实现中,return 子类型 [a] t
仍应遵循协方差规则,因为子类型位于 return 类型位置。
但是,我收到以下错误:
Error: Signature mismatch:
...
Values do not match:
val make : int -> [ `a ] t
is not included in
val make : int -> [< `a | `b ] t
File ".../cov.ml", line 3, characters 3-34:
Expected declaration
File ".../cov.ml", line 7, characters 7-11:
Actual declaration
关于如何让 OCaml 相信 make
函数确实是 returning [a | b] t
的有效子类型的任何建议?
我做了一些实验:
# type 'a t = Foo of int | Bar of string;;
type 'a t = Foo of int | Bar of string
# let make = function
| 0 -> (Foo 0 : [`a] t)
| _ -> (Bar "hi" : [`a] t);;
val make : int -> [ `a ] t = <fun>
# (make : int -> [< `a | `b] t);;
- : int -> [ `a ] t = <fun>
# let make2 : int -> [< `a | `b] t = make;;
val make2 : int -> [ `a ] t = <fun>
# let make3 = (make :> int -> [< `a | `b] t);;
val make3 : int -> [< `a | `b ] t = <fun>
所以,显然 OCaml 确实识别超类型关系,但仍然倾向于坚持更精确的子类型,除非给出强制转换。其他人可能知道类型理论的原因。但是你的问题只是
[...] how to convince OCaml [...]
我的回答是:像这样使用强制转换
module Test : sig
type +'a t
val make : int -> [< `a | `b] t
end = struct
type 'a t = Foo of int | Bar of string
let make = (function
| 0 -> (Foo 0 : [`a] t)
| _ -> (Bar "hi" : [`a] t)
:> int -> [< `a | `b] t)
end
我有以下代码:
module Test : sig
type +'a t
val make : int -> [< `a | `b] t
end = struct
type 'a t = Foo of int | Bar of string
let make = function
| 0 -> (Foo 0 : [`a] t)
| _ -> (Bar "hi" : [`a] t)
end
您可能会注意到,抽象类型 'a t
在其类型参数 'a
中被声明为协变的,并且 make
构造函数被声明为 returning 子类型 的多态变体案例 a
或 b
.
在我的 make
实现中,return 子类型 [a] t
仍应遵循协方差规则,因为子类型位于 return 类型位置。
但是,我收到以下错误:
Error: Signature mismatch:
...
Values do not match:
val make : int -> [ `a ] t
is not included in
val make : int -> [< `a | `b ] t
File ".../cov.ml", line 3, characters 3-34:
Expected declaration
File ".../cov.ml", line 7, characters 7-11:
Actual declaration
关于如何让 OCaml 相信 make
函数确实是 returning [a | b] t
的有效子类型的任何建议?
我做了一些实验:
# type 'a t = Foo of int | Bar of string;;
type 'a t = Foo of int | Bar of string
# let make = function
| 0 -> (Foo 0 : [`a] t)
| _ -> (Bar "hi" : [`a] t);;
val make : int -> [ `a ] t = <fun>
# (make : int -> [< `a | `b] t);;
- : int -> [ `a ] t = <fun>
# let make2 : int -> [< `a | `b] t = make;;
val make2 : int -> [ `a ] t = <fun>
# let make3 = (make :> int -> [< `a | `b] t);;
val make3 : int -> [< `a | `b ] t = <fun>
所以,显然 OCaml 确实识别超类型关系,但仍然倾向于坚持更精确的子类型,除非给出强制转换。其他人可能知道类型理论的原因。但是你的问题只是
[...] how to convince OCaml [...]
我的回答是:像这样使用强制转换
module Test : sig
type +'a t
val make : int -> [< `a | `b] t
end = struct
type 'a t = Foo of int | Bar of string
let make = (function
| 0 -> (Foo 0 : [`a] t)
| _ -> (Bar "hi" : [`a] t)
:> int -> [< `a | `b] t)
end