2012-01-07 55 views
3

我正在學習RX,並試圖將C#中的一些代碼移植到F#。 以下是C#示例使用定時器:F#RX使用定時器

Console.WriteLine("Current Time: " + DateTime.Now); 
var source = Observable.Timer(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(1)).Timestamp(); 
using (source.Subscribe(x => Console.WriteLine("{0}: {1}", x.Value, x.Timestamp))) 
     { 
     Console.WriteLine("Press any key to unsubscribe"); 
     Console.ReadKey(); 
     } 
Console.WriteLine("Press any key to exit"); 
Console.ReadKey(); 

以下是我的代碼試圖做同樣的:

#light 
open System 
open System.Collections.Generic 
open System.Linq 
open System.Reactive 
open System.Reactive.Linq 
open System.Reactive.Subjects 


printfn "Current Time: %A" DateTime.Now 

let source = Observable.Timer(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(1.0)).Timestamp() 
source.Subscribe(fun x -> printfn "%A %A" x.Value x.Timestamp) |> ignore 

但我得到編譯器錯誤:

錯誤1根據此計劃點之前的信息查找不確定類型的對象。在此程序點之前可能需要類型註釋來約束對象的類型。這可能會使查找得到解決。

我不知道x.Valuex.Timestamp怎麼樣。順便說一下,我也不知道如何在C#中使用F#重寫。 請爲我顯示正確的代碼。

回答

2

下面是一個「直接翻譯」成F#從C#:

open System 
open System.Reactive 
open System.Reactive.Linq 

printfn "Current Time: %A" DateTime.Now 
let source = Observable.Timer(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds  (1.0)).Timestamp() 
using (source.Subscribe(fun (x:Timestamped<int64>) -> printfn "%A %A" x.Value x.Timestamp)) 
    (fun _ -> 
     printfn "Press any key to unsubscribe" 
     Console.ReadKey() |> ignore 
    ) 

printfn "Press any key to stop" 
Console.ReadKey() |> ignore 

當運行允許它到5秒後看到1秒計時器事件是如何開始流入前

附錄 :lambda表達式中的輸入參數的類型,其依次是Iobservable.Subscribe()的參數是IObservable的值的類型,我們將其稱爲Subscribe(),即值的類型構成IObservablesource

反過來,source表示Observable.Timer(DateTimeOffset, TimeSpan)方法的結果,該方法返回一個可觀察的序列,該序列在適當的時間產生一個值,然後在每個週期之後產生一個值。該序列的類型爲IObservable<int64>

Timestamp()方法適用於IObservable<int64>時得到IObservable<Timestamped<int64>>

所以,最終我們sourceTimestamped<int64>類型,它上面的代碼段反映爲顯式類型中Subscribe()匿名函數的參數xIObservable

+0

嗨,Gene Belitski:非常感謝,您的代碼有效!但是我很難知道x的類型,就像在C#代碼中那樣,類型也是缺失的。 – 2012-01-07 20:45:44

+0

@John:由於涉及的類型的解釋需要更多空間,而不是最大允許評論的空間,所以我將它作爲我原始答案的附錄。爲了清楚起見,您可能希望使用[System.Reactive](http://msdn.microsoft.com/zh-cn/library/hh229356(v = VS.103).aspx)作爲參考來跟蹤這種類型轉換鏈。 – 2012-01-07 21:32:46

1

訂閱無法工作,因爲它已超載。如果你指定使用哪個超載,那麼它就可以工作。

(source.Subscribe : (Timestamped<int64> -> unit) -> IDisposable)(fun x -> printfn "%A %A" x.Value x.Timestamp) |> ignore 

如果使用Add方法而不是Subscribe,那麼類型將正確解析。

printfn "Current Time: %A" DateTime.Now 

let source = Observable.Timer(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(1.0)).Timestamp() 
source.Add(fun x -> printfn "%A %A" x.Value x.Timestamp) 

printfn "Press any key to stop" 
Console.ReadKey() |> ignore