首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >多态变体子类型实现不匹配签名。

多态变体子类型实现不匹配签名。
EN

Stack Overflow用户
提问于 2018-01-13 06:23:19
回答 1查看 459关注 0票数 7

我有以下代码:

代码语言:javascript
运行
复制
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构造函数被声明为返回多态变体案例ab的子类型。

在我的make实现中,返回子类型[a] t仍然应该遵循协方差规则,因为子类型位于返回类型位置。

但是,我得到以下错误:

代码语言:javascript
运行
复制
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函数确实正在返回有效的[a | b] t子类型的建议

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-13 13:14:35

我做了一些实验:

代码语言:javascript
运行
复制
# 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确实认识到超级类型的关系,但仍然倾向于坚持更精确的子类型,除非给予强制。其他人可能知道这种类型的理论原因。但因为你的问题

..。如何说服OCaml ..。

我的答案是:使用像这样的矫顽力

代码语言:javascript
运行
复制
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
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48237453

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档