gpt4 book ai didi

ocaml 格式化程序和值限制

转载 作者:行者123 更新时间:2023-12-04 22:20:25 25 4
gpt4 key购买 nike

编辑 : 对不起大家,我以为我的小考试已经完成了,结果不是。
我做了一个新的,真的应该是!

一旦我将格式化程序用作 Scanf 或 Printf 函数的参数,格式化程序类型就会分别绑定(bind)到输入或输出 channel 。
有没有办法让函数采用格式化程序(或字符串)并将其用作打印和阅读的格式化程序?

let fmt = format_of_string "%d,%d";;
Scanf.sscanf "2,2" fmt (fun x y -> x,y);;
fmt;;


- : (int -> int -> int * int, Scanf.Scanning.scanbuf, '_a, (int -> int -> int * int) -> int * int, (int -> int -> int * int) -> int * int, int * int) format6 = <abstr>

这意味着后续的 Printf.printf fmt 1 2;;给出类型错误。
这适用于 format_of_string 的每个组合和 Scanf.format_from_string像我尝试过的功能。

例子:
module Thing = struct

(* Just a helper for file IO *)
type 'a result = Success of 'a | Failure of exn;;
let with_out_file filename fn =
let out_ch = open_out filename in
let res = try Success (fn out_ch) with
exn -> Failure exn in
close_out out_ch;
match res with
| Success a -> a
| Failure a -> raise a;;

(* Uses the format string for writing *)
let print (fmt : ('a, 'b, 'c, 'd, 'e, 'f) format6) fn v =
with_out_file fn (fun x -> Printf.fprintf x fmt v);;

(* Uses the format string for reading *)
let read (fmt : ('a, 'b, 'c, 'd, 'e, 'f) format6) v =
Scanf.sscanf v fmt (fun x -> x);;

(* Where things break *)
let both fmt v =
read fmt "42\n";
print fmt "tfile" v;;
end;;


Error: This expression has type ('a -> 'b, Scanf.Scanning.scanbuf, 'c, ('d -> 'd) -> 'e, ('a -> 'b) -> 'f, 'f) format6 but an expression was expected of type                                                       
('a -> 'b, out_channel, unit, unit, unit, unit) format6
Type Scanf.Scanning.scanbuf is not compatible with type out_channel

对于 both 的最后一行功能,这似乎是有道理的,
但如果我删除 both模块中的函数,我可以调用 readprint使用相同的格式字符串(与参数相同的变量),它就可以工作。

所以,希望你们还没有放弃我;我该如何解决?
在这种情况下,eta-expansion 和类型注释似乎都不起作用?

最佳答案

你打的是臭名昭著的value restriction :

# let fmt = format_of_string "%d,%d";;
val fmt : (int -> int -> '_a, '_b, '_c, '_d, '_d, '_a) format6 = <abstr>

那些 '_a , '_b , '_c , '_d意思是“尽快确定类型”。它们不是参数,即 fmt不是多态值。相反,空列表是多态的:
# let emptiness = [] ;;
val emptiness : 'a list = []

现在我们有 'a而不是 '_a .但也许你已经知道这一切。关键是当我们申请 Printf.printffmt , 它的类型固定为
(int -> int -> unit, out_channel, unit, unit, unit, unit) format6

但是当我们申请 Scanf.sscanffmt它的类型固定为
(int -> int -> int * int, Scanf.Scanning.in_channel, '_a,
(int -> int -> int * int) -> int * int,
(int -> int -> int * int) -> int * int, int * int)
format6

这两种类型不兼容,因为 fmt不是多态的,你不能同时使用它。解决方案就是拥有两个副本, fmt_infmt_out .该解决方案有什么 Not Acceptable 地方吗?

关于ocaml 格式化程序和值限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25025091/

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