2014-06-25 8 views
2

Это мой код в C#Как использовать Observable.Zip в F #

Observable.Zip(ob1, ob2, (a, b) => a + b); 

Я пытаюсь преобразовать это в F # с помощью оператора Pipe-экспедиторских

ob1 |> Observable.Zip(ob2, Func<_,_,_> (fun a b -> a + b)) 

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

Любой ключ?

Следующие работы просто прекрасны, мне просто любопытно, могу ли я здесь работать оператором переадресации труб. Технически он должен взять ob1 с левой стороны в качестве первого параметра и взять два поставленных параметра как 2-й и 3-й справа?

Observable.Zip (ob1,ob2 ,Func<_,_,_>(fun a b -> a + b)) 
+1

просто используйте это (или скопируйте): https://github.com/fsprojects/FSharp.Reactive/blob/master/src/Observable.fs - btw: проблема в том, что Zip не является точной функцией – Carsten

+0

@ CarstenKönig Пожалуйста, обратите внимание на отправку определения функции 'zip' из модуля в качестве ответа! –

+0

Почему нет - я надеюсь, что у меня нет ошибок там (прямо сейчас на Linux/mono, и я как-то не могу получить Rx Nuget прямо сейчас :() – Carsten

ответ

5

Как уже упоминалось в комментарии вы можете реализовать простую оболочку, как это:

open System.Reactive.Linq 

    let zipWith (f : 'T -> 'U -> 'R) 
       (second: IObservable<'U>) 
       (first: IObservable<'T>) 
       : IObservable<'R> = 
     Observable.Zip(first, second, f) 

и это просто сделать, как вы хотели:

ob1 |> zipWith (fun a b -> a+b) ob2 

PS: это выглядит еще лучше если вы сделаете это так:

ob1 |> zipWith (+) ob2 
+0

+1: Выглядит правильно. Возможно, вам не нужно обертывать функцию в Func передать его Zip, но я также не могу проверить его легко сейчас. – scrwtp

+0

да спасибо - это правда, только что проверил его – Carsten

2

У вас, похоже, есть неправильные впечатления от работы оператора трубы, поэтому я попытаюсь их очистить.

Давайте делать вещи проще напечатать, и сказать, что мы имеем функции Foo и бар:

let foo (a, b, f) = f a b 
let bar a b f = f a b 

foo имеет более или менее ту же форму, Observable.Zip и принимает кортеж в качестве аргумента (это как Функции C# видны в F #), bar - это то же самое, но в карри.

Это работает:

foo (ob1, ob2, fun a b -> a + b) 
bar ob1 ob2 (fun a b -> a + b) 

Это не работает:

ob1 |> bar ob2 (fun a b -> a + b) 

Это потому, что оператор труба делает, принимает значение слева, и передавая его как последний аргумент функции справа. Вы должны были бы бар, чтобы определить, как это:

let bar b f a = f a b 

Именно поэтому функции, например, в модуле List определены таким образом, что фактический список передается в качестве последнего аргумента - что делает конвейерной работы в хороший способ.

Это также не работает:

ob1 |> foo (ob2, fun a b -> a + b) 

Помимо предыдущей задачи, она также потребует оператора трубы, чтобы заглянуть внутрь кортежа и прикрепить значение там, и это на самом деле не так, как это работает. Кортеж - это одно значение в F #.Функция, которая будет работать для этого примера, будет такой:

let foo (b, f) a = f a b 

Но ясно, что это не то, что мы хотим.

Вы все еще можете использовать Observable.Zip в моде трубопровода, как это:

ob1 |> fun x -> Observable.Zip(x, ob2, Func<_,_,_> (fun a b -> a + b)) 

Или просто пойти с оберткой другого ответа наводит на мысль.

Смежные вопросы