F # RX с использованием таймера - PullRequest
3 голосов
/ 07 января 2012

Я изучаю RX и пытаюсь перенести некоторый код из C # в F #.Ниже приведен пример использования таймера на C #:

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.Value и x.Timestamp.Кстати, я также не знаю, как переписать, используя в C # здесь, в F #.Пожалуйста, покажите мне правильный код для этого.

Ответы [ 2 ]

2 голосов
/ 07 января 2012

Ниже приведен «прямой перевод» на 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 секунды.

ADDENDUM : Тип входного аргумента в лямбда-выражении, который, в свою очередь, является аргументом Iobservable.Subscribe(), является типом значений IObservable, которые мы называем Subscribe(), т.е. тип значений, составляющих IObservable source.

В свою очередь, source представляет результат метода Observable.Timer(DateTimeOffset, TimeSpan), который возвращает наблюдаемую последовательность, которая создает значение в установленное время, а затем после каждого периода. Эта последовательность имеет тип IObservable<int64>.

Timestamp() метод при применении к IObservable<int64> дает IObservable<Timestamped<int64>>.

Итак, в конечном итоге наш source равен IObservable типа Timestamped<int64>, который приведенный выше фрагмент кода отражает как явный тип аргумента x анонимной функции в Subscribe().

1 голос
/ 08 января 2012

Подписка не работает, потому что она перегружена. Если вы укажете, какую перегрузку использовать, то это сработает.

(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
...