Generics 将curried kprintf作为函数参数传递
我在将Printf类函数作为参数传递时遇到了一个问题。 最终目标是创建一个定制的日志函数,该函数可以被注入到其他假定日志的方法中。所以,我学会了如何使用kprintf。但是如何将其结果向上传递到调用堆栈。 谁能帮我使下面的代码正常工作Generics 将curried kprintf作为函数参数传递,generics,f#,functional-programming,printf,Generics,F#,Functional Programming,Printf,我在将Printf类函数作为参数传递时遇到了一个问题。 最终目标是创建一个定制的日志函数,该函数可以被注入到其他假定日志的方法中。所以,我学会了如何使用kprintf。但是如何将其结果向上传递到调用堆栈。 谁能帮我使下面的代码正常工作 open System type logging () = let logWarning = let logToConsole msg = Console.WriteLine("WARN: {0} {1}", DateTime.Now,
open System
type logging () =
let logWarning =
let logToConsole msg = Console.WriteLine("WARN: {0} {1}", DateTime.Now, msg)
fun fmt -> Printf.kprintf logToConsole fmt
let doThingsWithLogging warningLogger =
warningLogger "%s %d %f" "DoThingsWithLogger" 3 3.29
warningLogger "%d %A" 3 "DoThingsAgain"
member __.RunTest() =
logWarning "%s %d %f" "String, int, float" 12 38.8
logWarning "%d %f %s" 83 128.9 "int, float, string"
doThingsWithLogging logWarning
let test = logging()
test.RunTest ()
如果您尝试在FSI中运行它,您将立即看到问题所在,warningLogger参数上的-type推断不允许编译对此函数的第二次调用。
我如何才能使它工作,使我可以使用warningLogger,作为正常的printf类型的函数?
非常感谢您。一般来说,F#不允许您将泛型函数作为参数传递。在您的示例中,这并不容易看到(因为格式字符串更复杂),但您可以在以下更简单的情况中看到这一点:
let foo f =
f 1
f 1.0
无法告诉编译器参数f
应该是一个泛型函数'a->unit
,因此这将无法编译
在您的示例中,最简单的解决方案可能是定义一个具有泛型LogWraning
方法的类型,然后传递该类型的实例。大概是这样的:
type Logger() =
member x.LogWarning fmt =
let logMessage msg = Console.WriteLine("WARN: {0} {1}", DateTime.Now, msg)
Printf.kprintf logMessage fmt
let doThingsWithLogging (logger:Logger) =
logger.LogWarning "%s %d %f" "DoThingsWithLogger" 3 3.29
logger.LogWarning "%d %A" 3 "DoThingsAgain"
doThingsWithLogging (Logger())