在外部强制执行多态类型变量

Posted

技术标签:

【中文标题】在外部强制执行多态类型变量【英文标题】:Enforcing a polymorphic type variable on an external 【发布时间】:2018-04-04 17:38:01 【问题描述】:

问题的根源在于这个external

external make : string -> 'a -> unit = "debug"

我需要与任何类型一起使用:

let debug = make "name:space:a"

let _ = debug "log this thing"
let _ = debug 42

很遗憾,这会导致最后一行出现以下错误:

此表达式的类型为 int,但表达式应为字符串类型

所以我需要使类型参数显式地多态,但据我所知,由于某种原因,这只能在附加到 let 绑定的类型注释中完成。将其添加到外部会产生语法错误。所以我尝试:

let debug : 'a. 'a -> unit = make "name:space:a"

这当然会导致错误:

此定义的类型为 'a -> 单元,它不如 'a0 通用。 'a0 -> 单位

所以我尝试了另一种欺骗系统的方法,并在external之后添加了这个:

let make : 'a. string -> 'a -> unit = make

令我惊讶的是,这行并没有给我类似的类型错误,但似乎只是忽略了类型注释并继续在 let debug ... 上给我同样的错误。

这让我很困惑,并提出以下问题:

    真的不能用多态类型定义外部吗? 不管 1 的答案如何,为什么不能对外部使用显式多态类型注释? 为什么let make ... 上的类型注释完全被忽略了?

注意:我使用的是 4.02.3 上的 BuckleScript。在线游乐场here.

【问题讨论】:

【参考方案1】:

这是值限制,不是使用external 的结果。 (之前的讨论,众多讨论之一:The value restriction。)

你对debug的定义是一个函数应用,所以不能泛化(做成多态)。

解决办法是做eta扩展:

let debug x = make "name:space:a" x

现在你对debug 的定义是一个可以泛化的lambda。

(之前讨论的eta扩展:Why does OCaml sometimes require eta expansion?)

【讨论】:

嗯,我不确定我是否理解如果我被允许明确地使其具有多态性,值限制将如何应用。该函数返回单位,因此对于任何类型的不透明值来说,它都只是一个黑洞,不是吗?此外,虽然 eta 扩展可以从类型的角度解决问题,但它会破坏让函数返回另一个函数的目的,而不仅仅是启用部分应用程序。 您不能使用注释来绕过值限制,这通常是不合理的。但是,值限制并不精确,它有点过于严格。你可以很容易地找到禁止泛化的无害案例。

以上是关于在外部强制执行多态类型变量的主要内容,如果未能解决你的问题,请参考以下文章

Java Review (十面向对象----多态)

java-多态性

多态性

课堂作业8多态

4.7 多态

Hibernate LocalDateTime:Postgresql 模式生成在外部 Tomcat 中创建类型为“bytea”的列