Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Functional programming 如何积累观测值_Functional Programming_F# - Fatal编程技术网

Functional programming 如何积累观测值

Functional programming 如何积累观测值,functional-programming,f#,Functional Programming,F#,我应该定义一个函数,它将返回IObservable您可以链接一个可观察对象。在可观察对象之后选择。扫描以获得正确的类型签名 let accumulate (f:'t -> 'a -> 't * 'u option) t obs = obs |> Observable.scan (fun _ x -> snd (f t x)) None |> Observable.choose id 函数fun\ux->snd(f t x)不完整。线索是第一

我应该定义一个函数,它将返回IObservable您可以链接一个
可观察对象。在
可观察对象之后选择
。扫描
以获得正确的类型签名

let accumulate (f:'t -> 'a -> 't * 'u option) t obs =
    obs
    |> Observable.scan (fun _ x -> snd (f t x)) None
    |> Observable.choose id

函数
fun\ux->snd(f t x)
不完整。线索是第一个参数
\uu
被忽略,结果元组的第一部分被调用
snd
丢弃

没有累加,因为
ftx
总是使用最初传递给
acculate
的相同值
t
调用。原始的
t
应该是初始值,并且应该作为第二个参数的一部分传递给
scan

f:'t->'a->'t*'u选项产生的元组的第一部分是累积值。这就是需要返回到
scan
的部分,以便再次传递到
f
,并一次又一次地累积

在您的问题中,当元组的第二部分是
Some'u
时,需要累积并传递一个事件。所以问题是如何做到这两个:累加
't
和过滤
'u

答案是将累积值与
Some'u
相结合,这就是
f
的作用。因此,您需要将元组保持为
scan
状态,然后使用
choose
snd
仅保留第二部分

这就是您正在寻找的:

let accumulate (f:'t -> 'a -> 't * 'u option) t obs =
    obs
    |> Observable.scan (fun (acc, _) x -> f acc x) (t, None)
    |> Observable.choose snd

理解
扫描

scan
是一个函数,它通过将一个变化的状态与一系列值一起传递给一个函数来承载该状态。特别是,它可用于累积值,例如
int
运行总计:

let keepTotal obs =
    obs
    |> Observable.scan (fun total v -> total + v) 0
这相当于在命令式代码中使用可变的
total

let mutable total = 0

let keepTotal2 obs =
    obs
    |> Observable.map (fun v -> 
        total <- total + v
        total
    )
尽管这个变量在函数式编程中使用了一个难看的可变变量(而且是不必要的),但它在功能上是正常的,因为变量
acc
是内部变量,而
acgregate2
之外的任何代码都看不到它。不过还是很难看

let keepTotal obs =
    obs
    |> Observable.scan (fun total v -> total + v) 0
let mutable total = 0

let keepTotal2 obs =
    obs
    |> Observable.map (fun v -> 
        total <- total + v
        total
    )
let accumulate2 (f:'t -> 'a -> 't * 'u option) t obs =
    let mutable acc = t
    obs
    |> Observable.choose (fun x ->
        let acc2, uOp = f acc x
        acc <- acc2
        uOp
    )