2012-01-07 89 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