【发布时间】:2019-01-25 22:21:11
【问题描述】:
我目前正在尝试学习 F#,但遇到了一个我无法解决且在 google 上找不到任何答案的问题。
最初我想要一个日志函数,它可以像 printf 系列函数一样工作,我可以提供一个格式字符串和一些参数(静态检查),但它会在打印出来之前添加一些元数据。通过谷歌搜索,我发现使用如下函数可以做到这一点:
let LogToConsole level (format:Printf.TextWriterFormat<'T>) =
let extendedFormat = (Printf.TextWriterFormat<string->string->'T> ("%s %s: " + format.Value))
let date = DateTime.UtcNow.ToString "yyyy-MM-dd HH:mm:ss.fff"
let lvl = string level
printfn extendedFormat date lvl
将printfn 函数作为该函数的最后一行允许 printf 语法的类似 varargs 的魔力,从而返回部分应用的 printfn 方法以允许调用者完成应用参数。
但是,如果我有多个具有相同签名的此类函数,例如 LogToConsole、LogToFile 和其他函数,我怎么能编写一个函数来调用它们来保持这种部分应用程序的魔力?
基本我正在寻找如何实现函数MultiLog
这将允许我从单个函数调用中调用多个类似 printf 的函数,例如在下面的 ResultIWant 函数中:
type LogFunction<'T> = LogLevel -> Printf.TextWriterFormat<'T> -> 'T
let MultiLog<'T> (loggers:LogFunction<'T>[]) level (format:Printf.TextWriterFormat<'T>) :'T =
loggers
|> Seq.map (fun f -> f level format)
|> ?????????
let TheResultIWant =
let MyLog = MultiLog [LogToConsole; LogToFile]
MyLog INFO "Text written to %i outputs" 2
也许这个问题的本质可以更简洁地抓住:给定一个具有相同签名的函数列表,我如何才能部分地使用相同的参数应用它们?
type ThreeArg = string -> int -> bool -> unit
let funcs: ThreeArg seq = [func1; func2; func3]
let MagicFunction = ?????
// I'd like this to be valid
let partiallyApplied = MagicFunction funcs "string"
// I'd also like this to be valid
let partiallyApplied = MagicFunction funcs "string" 255
// and this (fullyApplied will be `unit`)
let fullyApplied = MagicFunction funcs "string" 255 true
【问题讨论】: