Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ocaml 为什么类型推断算法会因为“Fun.flip Option.bind”而混淆?_Ocaml_Type Inference_Value Restriction - Fatal编程技术网

Ocaml 为什么类型推断算法会因为“Fun.flip Option.bind”而混淆?

Ocaml 为什么类型推断算法会因为“Fun.flip Option.bind”而混淆?,ocaml,type-inference,value-restriction,Ocaml,Type Inference,Value Restriction,模块中函数声明的常见签名是当最后一个参数的类型为main state module.t时。就像在“列表”模块中一样。此表单打开了使用“|>”运算符的功能,如: [1;2;3]|>List.filter>2 |>List.map-1 |>List.fold_左0+ 但“Option”模块中的函数“bind”不遵循此形式。它的第一个参数是'Option.t' val bind:'a option->'a->'b option->'b option 但是好的,我可以改变它。我用参数的相反顺序声明了函数

模块中函数声明的常见签名是当最后一个参数的类型为main state module.t时。就像在“列表”模块中一样。此表单打开了使用“|>”运算符的功能,如:

[1;2;3]|>List.filter>2 |>List.map-1 |>List.fold_左0+ 但“Option”模块中的函数“bind”不遵循此形式。它的第一个参数是'Option.t'

val bind:'a option->'a->'b option->'b option 但是好的,我可以改变它。我用参数的相反顺序声明了函数“opt_bind”

让opt_bind=Fun.flip Option.bind 但是这个不行。下面的代码是用下面的错误编译的

a型=整数的a型 类型b=int的类型b 设fx=A x 设g A x=某个B x 让opt_bind=Fun.flip Option.bind 让结果= 一些42 |>opt|u绑定f |>选择绑定 错误:此表达式具有类型a->b选项,但表达式应为>类型int->a选项。类型a与类型int不兼容

同样的情况

让结果= 设x=opt_绑定f约42 in 设x=opt_绑定gx-in x 即使在我注意到所有类型之后,我仍然有同样的问题

让f:int->a option=funx->Some a x 让g:a->b option=fun a x->Some b x 让opt_绑定:'a->'b option->'a option->'b option= Fun.flip Option.bind 让结果:b选项= 设x:a option=opt_绑定f约42 in 设x:b option=opt_绑定gx in x;; 但是

让结果= 设x=Option.bind约42 f in 设x=Option.bind x g in x 很好

为什么“opt_bind”对“g”有错误的类型期望,好像“opt_bind”不是泛型的?
如何将“bind”与“|>”符号一起使用?

您的问题是您对opt|u bind的定义不够多态。由于您将其定义为Fun.flip to Option.bind的应用程序,因此由于值限制,无法使其具有多态性

如果您这样定义它:

let opt_bind a b = Fun.flip Option.bind a b
let opt_bind a b = Option.bind b a
或者,等价地,像这样:

let opt_bind a b = Fun.flip Option.bind a b
let opt_bind a b = Option.bind b a
然后事情就会发生了

如果您询问opt_bind定义的类型,您会发现问题:

# let opt_bind = Fun.flip Option.bind;;
val opt_bind :
  ('_weak3 -> '_weak4 option) -> '_weak3 option ->
  '_weak4 option = <fun>
弱类型变量告诉您结果函数不是多态的

本质区别在于Fun.flip Option.bind在语法上是一个应用程序,是一个函数调用。这样的表达式不能是多态的。这两种替代形式将bind_opt定义为lambda a函数值,这是值限制术语中的语法值

值限制是为了确保多态函数是可靠的,即它们不允许对值进行不适当的操作


我选择在OCaml中实现的值限制的参考是本文:

您的问题是您对opt_bind的定义不够多态。由于您将其定义为Fun.flip to Option.bind的应用程序,因此由于值限制,无法使其具有多态性

如果您这样定义它:

let opt_bind a b = Fun.flip Option.bind a b
let opt_bind a b = Option.bind b a
或者,等价地,像这样:

let opt_bind a b = Fun.flip Option.bind a b
let opt_bind a b = Option.bind b a
然后事情就会发生了

如果您询问opt_bind定义的类型,您会发现问题:

# let opt_bind = Fun.flip Option.bind;;
val opt_bind :
  ('_weak3 -> '_weak4 option) -> '_weak3 option ->
  '_weak4 option = <fun>
弱类型变量告诉您结果函数不是多态的

本质区别在于Fun.flip Option.bind在语法上是一个应用程序,是一个函数调用。这样的表达式不能是多态的。这两种替代形式将bind_opt定义为lambda a函数值,这是值限制术语中的语法值

值限制是为了确保多态函数是可靠的,即它们不允许对值进行不适当的操作


对于值限制,特别是在OCaml中实现的值限制,我选择的参考是本文:

类型注释不能绕过值限制。它们并不意味着你在这种情况下的想法——opt_-bind仍然不是多态的;相反,“a”和“b”用弱类型变量统一起来。注释中类型变量的这种误导性语义可以说是OCaml的一个缺陷。您需要使用至少一个参数来扩展定义,而不是注释,如Jeffrey的答案所示。这避免了值限制。另请参见,类型批注无法绕过值限制。它们并不意味着你在这种情况下的想法——opt_-bind仍然不是多态的;相反,“a”和“b”用弱类型变量统一起来。注释中类型变量的这种误导性语义可以说是OCaml的一个缺陷。您需要使用至少一个参数来扩展定义,而不是注释,如Jeffrey的答案所示。这避免了值限制。另请参见,