2011-04-06 126 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