F#RX将异步模式转换为可观察序列

时间:2012-01-08 13:35:57

标签: f# system.reactive

我想将一些C#for RX转换成F#代码。 以下是C#代码:

Stream inputStream = Console.OpenStandardInput();
var read = Observable.FromAsyncPattern<byte[], int, int, int>    
    (inputStream.BeginRead, inputStream.EndRead);
byte[] someBytes = new byte[10];
IObservable<int> source = read(someBytes, 0, 10);
IDisposable subscription = source.Subscribe(
                        x => Console.WriteLine("OnNext: {0}", x),
                        ex => Console.WriteLine("OnError: {0}",                                   ex.Message),
                        () => Console.WriteLine("OnCompleted"));
Console.ReadKey();

以下是我在F#中的代码:

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

let inputStream: Stream = Console.OpenStandardInput()
let read = Observable.FromAsyncPattern<byte[], int, int, int>(inputStream.BeginRead, inputStream.EndRead)
let someBytes: byte[] = Array.create 10 (byte(0))
let source: IObservable<int> = read(someBytes, 0, 10)

let subscription:IDisposable = 
                 source.Subscribe((fun x -> printfn "OnNext %A" x), 
                               (fun ex -> printfn "OnError %A" ex.Message), 
                               (fun _ -> printfn "OnComplete"))
Console.ReadKey() |> ignore

但是我遇到了以下编译器错误:

  

错误1方法'FromAsyncPattern'没有重载匹配。该   可用的重载如下所示(或在错误列表窗口中)。

     

错误2可能的过载:   'Observable.FromAsyncPattern&LT;' TResult&GT;(开始:   Func&lt; AsyncCallback,obj,IAsyncResult&gt;,end:   Func&lt; IAsyncResult,'TResult&gt;):Func&lt; IObservable&lt;'TResult&gt;&gt;'。

     

错误3可能的过载:   'Observable.FromAsyncPattern&LT;' T1'TResult&GT;(开始:   Func&lt;'T1,AsyncCallback,obj,IAsyncResult&gt;,end:   Func&lt; IAsyncResult,'TResult&gt;):Func&lt;'T1,IObservable&lt;'TResult&gt;&gt;'。

似乎F#中的编译器没有识别出过载,但我不知道如何使F#编译器更聪明地完成它的工作。 请告诉我你的代码。 谢谢,周末愉快。 约翰

1 个答案:

答案 0 :(得分:3)

问题是FromAsyncPattern的参数是委托(类型Func<...>)而不是F#函数(类型_->_)。因此,您不能只传递一个方法(如inputStream.BeginRead),但需要传递一个显式函数(例如fun a b c d e -> inputStream.BeginRead(a,b,c,d,e))或显式构造一个委托(例如System.Func<_,_,_,_,_,_>(fun a b c d e -> inputStream.BeginRead(a,b,c,d,e)))。 / p>

在你的情况下,我认为

let read = Observable.FromAsyncPattern(
            (fun a b c d e -> inputStream.BeginRead(a,b,c,d,e)), 
            fun r -> inputStream.EndRead r)

应该有用。