是否可以在不丢失 ocaml 中参数的多态类型的情况下设置函数的默认值
Is this possible to set a default value of a function without loosing the polymorphic type of an argument in ocaml
我有这个功能可以在文件中添加日志:
let log_datas f file (datas: 'a list) =
let oc = open_out file.file_name in
List.iter (fun x -> Printf.fprintf oc "%s" @@ f x) datas;
close_out oc
let () = let f = string_of_int in log_datas f {file_name="log"} [1;2]
哪个有效。
我试图让它默认接受字符串列表作为参数:
let log_datas ?(f:'a -> string = fun x -> x^"\n") file (datas: 'a list) =
let oc = open_out file.file_name in
List.iter (fun x -> Printf.fprintf oc "%s" @@ f x) datas;
close_out oc
但是当我尝试
let () = let f = string_of_int in log_datas ~f {file_name="log"} [1;2]
我遇到类型错误
23 | let () = let f = string_of_int in log_datas ~f {file_name="log"} [1;2]
^
Error: This expression has type int -> string
but an expression was expected of type string -> string
Type int is not compatible with type string
一个明显的解决方案是创建 2 个函数,一个不带 f
参数,一个带 f
参数。但我想知道,还有其他解决方法吗?
不,这是不可能的,您必须指定两个参数以保持多态性。基本上,您的示例可以提炼为
let log ?(to_string=string_of_int) data =
print_endline (to_string data)
如果 OCaml 会保持它的多态性,那么将允许以下内容,
log "hello"
和 string_of_int "hello"
类型不正确。
所以你必须保留这两个参数,例如
let log to_string data =
print_endline (to_string data)
我还建议查看 Format
模块并定义您自己的多态函数,该函数使用格式规范来定义不同类型数据的写入方式,例如,
let log fmt =
Format.kasprintf print_endline fmt
用我们自己的日志工具代替 print_endline
。 log
函数可以用作 printf
,例如,
log "%s %d" "hello" 42
我有这个功能可以在文件中添加日志:
let log_datas f file (datas: 'a list) =
let oc = open_out file.file_name in
List.iter (fun x -> Printf.fprintf oc "%s" @@ f x) datas;
close_out oc
let () = let f = string_of_int in log_datas f {file_name="log"} [1;2]
哪个有效。
我试图让它默认接受字符串列表作为参数:
let log_datas ?(f:'a -> string = fun x -> x^"\n") file (datas: 'a list) =
let oc = open_out file.file_name in
List.iter (fun x -> Printf.fprintf oc "%s" @@ f x) datas;
close_out oc
但是当我尝试
let () = let f = string_of_int in log_datas ~f {file_name="log"} [1;2]
我遇到类型错误
23 | let () = let f = string_of_int in log_datas ~f {file_name="log"} [1;2]
^
Error: This expression has type int -> string
but an expression was expected of type string -> string
Type int is not compatible with type string
一个明显的解决方案是创建 2 个函数,一个不带 f
参数,一个带 f
参数。但我想知道,还有其他解决方法吗?
不,这是不可能的,您必须指定两个参数以保持多态性。基本上,您的示例可以提炼为
let log ?(to_string=string_of_int) data =
print_endline (to_string data)
如果 OCaml 会保持它的多态性,那么将允许以下内容,
log "hello"
和 string_of_int "hello"
类型不正确。
所以你必须保留这两个参数,例如
let log to_string data =
print_endline (to_string data)
我还建议查看 Format
模块并定义您自己的多态函数,该函数使用格式规范来定义不同类型数据的写入方式,例如,
let log fmt =
Format.kasprintf print_endline fmt
用我们自己的日志工具代替 print_endline
。 log
函数可以用作 printf
,例如,
log "%s %d" "hello" 42