Functional programming 如何积累观测值
我应该定义一个函数,它将返回IObservable您可以链接一个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)不完整。线索是第一
可观察对象。在可观察对象之后选择
。扫描
以获得正确的类型签名
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
)