gpt4 book ai didi

ocaml - 用OCaml编写此内容的正确方法是什么?

转载 作者:行者123 更新时间:2023-12-04 23:04:57 26 4
gpt4 key购买 nike

type t = MyInt of int | MyFloat of float | MyString of string
let foo printerf = function
| MyInt i -> printerf string_of_int i
| MyFloat x -> printerf string_of_float x
| MyString s -> printerf (fun x -> x) s


它报告:

Error: This expression has type float -> string
but an expression was expected of type int -> string

最佳答案

移植此确切代码段的正确方法(我想这是
来自thiswebpage的)
一流的多态性,如以下常见问题解答条目中所述:How to writea function with polymorphicarguments?。请
请阅读FAQ条目,但是为了快速参考,这里是一个工作代码示例:

type t = MyInt of int | MyFloat of float | MyString of string

type 'b printer = { print : 'a . ('a -> string) -> 'a -> 'b }
let foo erf = function
| MyInt i -> erf.print string_of_int i
| MyFloat x -> erf.print string_of_float x
| MyString s -> erf.print (fun x -> x) s

let () = foo
{ print = fun printer data -> print_endline (printer data) }
(MyString "Hello World!")


但是请注意,您实际上并不需要这个一流的
多态性在这里。根据参数, printer唯一可以
'a类型的数据传递给打印功能
'a -> string。因此,打印机的行为是完全确定的
通过对所得的 string数据进行处理。换句话说,
类型 'b printer与类型 string -> 'b同构,它带来了
没有其他信息。所以你可以这样写:

let foo erf = function
| MyInt i -> erf (string_of_int i)
| MyFloat x -> erf (string_of_float x)
| MyString s -> erf s

let () = foo print_endline (MyString "Hello World!")


foo的类型现在为 (string -> 'a) -> t -> 'a。这被称为
延续传递样式:从中获得 'a的唯一方法
类型是在字符串上调用参数函数,所以实际上
除了返回字符串,然后调用函数(继续)外,无非
在上面。可以改写为:

let foo = function
| MyInt i -> string_of_int i
| MyFloat x -> string_of_float x
| MyString s -> s

let () = print_endline (foo (MyString "Hello World!"))


长话短说:您显示的代码过于复杂,并且
它似乎构成的问题被夸大了。不需要
这里是一个复杂的类型系统。 (但您当然可以找到更好的选择
常见问题解答中展示的一流多态性的示例是
实际上有用。只是这个例子很烂...)

历史和科学背景

问题所要求的关于一流多态性的历史性保留。

'a . ('a -> string) -> 'a -> 'b表示“对于所有 'a('a -> string) -> 'a -> 'b”。它是在类型变量 'a(由 'a .位“定义”)中多态的类型,并具有自由变量 'b(定义为 printer类型的参数) 。

上面代码的第一版中 foo的类型是 'b printer -> t -> 'b。可以理解为对 System F类型进行编码

forall 'b . (forall 'a . ('a -> string) -> 'a -> 'b) -> t -> 'b


ML类型推断算法是将类型推断为仅限于“前缀多态性”,即所有类型变量都在前面进行量化的类型。上面类型中的 'b就是这种情况,但在(多态)参数中量化的 'a则不是这种情况。严格遵守ML(Hindley-Damas-Milner)推理系统的这种限制的类型系统不会推断该类型,因此会拒绝需要将其视为错误类型的程序(这不是“错误”,而是“我无法证明它是正确的”) )。

这种限制使得推理系统既可以判定(整个系统F的类型推理是不可判定的(Joe B. Wells)),也可以是“主要的”(如果您不知道什么是主体类型,请参见 this SO discussion;简而言之,这意味着推理引擎总是选择最通用的类​​型),但它也拒绝类型正确的程序,这是安全类型系统的常见祸根。

大多数ML语言(OCaml,Haskell ...)在某种程度上都遇到了他们真正希望能够编写的代码的限制。对于90年代的OCaml,当使用该语言对面向对象的编程模式进行编码时(请参见 examples in the manual)。

这就是为什么在方法类型中首先引入一流的多态性,然后将其扩展到记录的原因(一流的模块是独立的,并且是最近才添加的模块,它也允许这样做)。有一个很好的理由说明,在某种意义上为什么这仍然或多或少地局限于具有“字段”的“事物”,因为这为放置(必要的)多态注释提供了一种自然的方式,而字段投影对于类型检查器来测试实例化多态值的需要-如果可以的话,这会使理论更简单。

有关OCaml社区在此期间的研究工作,请参见例如 Extending ML with Semi-Explicit Higher-Order Polymorphism,Jacques Garrigue和DidierRémy,1997。开发了一流的多态性的其他方法(请参见Dider Le Botlan的 的文献综述),并发现了其他用例,特别是Haskell中的 ST monad( Recasting MLF,Simon Peyton Jones和John Launchbury,1994)。

关于ocaml - 用OCaml编写此内容的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14707651/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com