2011-04-06 77 views
6

我想创建一个框架来做一些文件和数据的处理。我正在努力的一个领域是如何为框架提供一个日志记录功能,允许框架报告消息,而不必知道正在使用的日志记录。如何使用printf风格日志参数创建F#函数?

let testLogger (source:seq<'a>) logger = 
    logger "Testing..." 
    let length = source |> Seq.length 
    logger "Got a length of %d" length 


let logger format = Printf.kprintf (printfn "%A: %s" System.DateTime.Now) format 
testLogger [1; 2; 3] logger 

理想我想这个代码工作,但我不能工作了如何通过记录仪功能研究。

+0

您可能感兴趣的:http://stackoverflow.com/questions/5277902/printf-style-logging-for-f – Daniel 2011-04-06 16:41:57

+0

我见过那个,但它不能帮助我,因为我不' t要框架知道log4net – 2011-04-06 16:44:53

+0

检查出第一个答案,它与log4net无关。 – Daniel 2011-04-06 16:46:25

回答

10

不幸的是,你不能传似printf功能参数等功能,然后使用他们与多个不同的论点。问题是printfPrintf.TextWriterFormat<'a> -> 'a类型的通用函数。替代类型参数'a的实际类型是某种函数类型,每次使用printf时都会有所不同(例如'a == string -> unit等于"%s"等)。

在F#中,不能拥有本身是泛型函数的函数的参数。通用函数必须是一些全局函数,但是您可以通过实际对字符串进行某种操作的函数对其进行参数化。实际上,这就是kprintf,但你可以说出你的函数更好:

let logPrintf logger format = 
    Printf.kprintf logger format 

的日志记录器参数化功能的一个例子是:

let testLogger (source:seq<'a>) logger = 
    logPrintf logger "Testing..." 
    let length = source |> Seq.length 
    logPrintf logger "Got a length of %d" length 


let logger = printfn "%A: %s" System.DateTime.Now 
testLogger [1; 2; 3] logger 
12

正如托马斯指出,在F#功能可以” t需要多态参数。在这种情况下,我认为Tomas的方法非常好,因为您可能只需要能够传递用于记录的string -> unit函数。

但是,如果你真的想绕过一个多态函数相当于,一个解决办法是建立一个简单的类型有一个通用的方法,并通过该类型的实例:

type ILogger = abstract Log : Printf.StringFormat<'a,unit> -> 'a 

let testLogger (source:seq<'a>) (logger:ILogger) = 
    logger.Log "Testing..." 
    let length = source |> Seq.length   
    logger.Log "Got a length of %d" length 

let logger = { 
    new ILogger with member __.Log format = 
     Printf.kprintf (printfn "%A: %s" System.DateTime.Now) format } 

为了使这项工作更加精美,类型推断,你可以定义一个模块,一个简单的辅助功能:

module Log = 
    let logWith (logger : ILogger) = logger.Log 

let testLogger2 (source:seq<'a>) logger = 
    Log.logWith logger "Testing..." 
    let length = source |> Seq.length   
    Log.logWith logger "Got a length of %d" length 

这最后的结果看起来很像托马斯的解决方案,但给你的,你如何定义更多的灵活性,你记录器,可能实际上也可能不实际在这种情况下对你有用。

+0

+1我很喜欢你的第一种方法,因为你可以避免全局功能。 – 2011-04-07 01:11:23

+0

好方法。我将Tomas标记为正确的答案,但我确实喜欢这种方法,我可能会使用它 – 2011-04-07 06:10:55