【发布时间】:2013-03-30 20:46:33
【问题描述】:
我想在 F# 中创建一个函数,它接受 printf 样式的函数作为参数,并使用该参数输出数据。用法如下所示:
OutputStuff printfn
我的第一次尝试是让编译器为我解决所有问题:
let OutputStuff output =
output "Header"
output "Data: %d" 42
失败是因为它认为output 是一个接受string 并返回unit 的函数,因此第二次调用失败。
接下来我尝试声明output 与printfn 具有相同的签名:
let OutputStuff (output : Printf.TextWriterFormat<'a> -> 'a) =
output "Header"
output "Data: %d" 42
这失败了,因为编译器确定output 的真实类型是Printf.TextWriterFormat<string> -> unit,所以第二次调用再次失败。它还会生成警告 FS0064,表明第一次调用 output 会导致代码没有类型注释那么通用,这是问题的症结所在。
最后,我尝试将输出函数声明为单独的类型缩写:
type OutputMe<'a> = Printf.TextWriterFormat<'a> -> 'a
let OutputStuff (output : OutputMe<'a>) =
output "Header"
output "Data: %d" 42
此操作失败,结果与上一次尝试相同。
如何说服编译器不要专门化 output 的类型并将其保留为 Printf.TextWriterFormat<'a> -> 'a?
【问题讨论】:
-
你真的需要传递类似 printf 的函数本身吗?如果你想使用某个函数,它需要一个
string,并且你想用格式化的字符串调用它,只需在你的函数中使用Printf.ksprintf。 -
您可能还会发现这很有用——在此文件 (Pervasive.fs) 的底部,我编写了一些函数,它们采用任意格式的字符串并在底层使用
Printf.ksprintf。
标签: f# type-inference