首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OCaml坚持认为函数不是多态函数,但不要指定类型

OCaml坚持认为函数不是多态函数,但不要指定类型
EN

Stack Overflow用户
提问于 2018-05-22 04:57:43
回答 3查看 358关注 0票数 2

是否可以显式地写下一个非多态类型,但是延迟了统一,比如下划线类型?

因此,在类型检查过程中,OCaml有时会生成带有前导下划线(例如_a)的顶级打印类型。具体来说,在实例化一个空的Hashtbl.t时,以及在其他一些情况下,这些都会出现。

代码语言:javascript
复制
# Hashtbl.create 1;;
- : ('_a, '_b) Hashtbl.t = <abstr>

但是,用户不能在源代码中显式引用这些类型。

代码语言:javascript
复制
# (5: int);;
- : int = 5
# (5: 'a);;
- : int = 5
# (5: '_a);;
Error: The type variable name '_a is not allowed in programs

您可以通过利用OCaml中缺乏更高级别的多态性来创建显式非多态函数。

代码语言:javascript
复制
# let id = snd ((), fun y -> y);;
val id : '_a -> '_a = <fun>
# (fun () -> fun y -> y) ();;
- : '_a -> '_a = <fun>

我想做些类似的事情

代码语言:javascript
复制
let id : <some magical type> = fun x -> x

而不是依赖于可能在未来消失的类型系统的限制。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-05-22 05:24:47

您可以利用这样一个事实:引用是不可泛化的。

代码语言:javascript
复制
# let id = let rx = ref [] in fun x -> rx := [x]; rx := []; x;;
val id : '_weak1 -> '_weak1 = <fun>

我认为引用的这个属性不太可能改变。

我假设您希望这个版本的id在第一次实际使用时假设一个单一的类型:

代码语言:javascript
复制
# id "yes";;
- : string = "yes"
# id;;
- : string -> string = <fun>

如果您在实际代码中使用这一点,那么它需要在模块结束之前得到一个具体的类型。不能将弱类型变量保留在未定义的位置,否则将得到以下错误:

代码语言:javascript
复制
Error: The type of this expression, '_weak1 -> '_weak1,
       contains type variables that cannot be generalized
票数 2
EN

Stack Overflow用户

发布于 2018-05-22 11:03:21

另外两个答案基本上利用了这样一个事实,即只有值是广义的,所以如果将定义封装在不是值的东西中,它就不会被泛化。因此,把它交给id函数就成了诀窍。

但是,如果考虑到放宽的值限制,则不起作用:

代码语言:javascript
复制
# let nil = id [] ;;
val nil : 'a list = []

因此,您需要确保您想要的类型变量不会出现在协变量位置。在第一个例子中,它出现在箭头的左边,所以它很好。否则,您需要通过隐藏类型定义和省略方差注释来确保它的工作。

代码语言:javascript
复制
module M : sig
  type 'a t
  val make : 'a list -> 'a t
end = struct
  type 'a t = 'a list
  let make x = x
end

let x = M.make []
val x : '_weak1 M.t
票数 2
EN

Stack Overflow用户

发布于 2018-05-22 07:23:54

我同意Jeffrey Scofield's answer的观点,但在我看来,最好避免引用,您可以在没有引用的情况下实现相同的行为:

代码语言:javascript
复制
# let id = let id = fun x -> x in id id;;
val id : '_weak1 -> '_weak1 = <fun>

之后,如果您需要使用其他签名(例如eq : '_weak2 -> '_weak2 -> bool )的函数,那么您所需要的就是以正常的方式实现eq并将其传递给id

代码语言:javascript
复制
# let eq =
    let id = let id = fun x -> x in id id in
    let eq = (=) in (id (eq));;
val eq : '_weak2 -> '_weak2 -> bool = <fun>
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50460061

复制
相关文章

相似问题

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