在外部强制执行多态类型变量
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 扩展可以从类型的角度解决问题,但它会破坏让函数返回另一个函数的目的,而不仅仅是启用部分应用程序。 您不能使用注释来绕过值限制,这通常是不合理的。但是,值限制并不精确,它有点过于严格。你可以很容易地找到禁止泛化的无害案例。以上是关于在外部强制执行多态类型变量的主要内容,如果未能解决你的问题,请参考以下文章
Hibernate LocalDateTime:Postgresql 模式生成在外部 Tomcat 中创建类型为“bytea”的列