F# 使用一个枚举应用多个聚合函数

F# 使用一个枚举应用多个聚合函数,f#,sequence,F#,Sequence,假设我有一系列处理序列的函数,我想以以下方式将它们结合使用: let meanAndStandardDeviation data = let m = mean data let sd = standardDeviation data (m, sd) 上面的代码将枚举该序列两次。我对一个函数感兴趣,它将给出相同的结果,但只枚举序列一次。此函数类似于以下内容: magicFunction (mean, standardDeviation) data let maxv =

假设我有一系列处理序列的函数,我想以以下方式将它们结合使用:

let meanAndStandardDeviation data = 
    let m = mean data
    let sd = standardDeviation data
    (m, sd)
上面的代码将枚举该序列两次。我对一个函数感兴趣,它将给出相同的结果,但只枚举序列一次。此函数类似于以下内容:

magicFunction (mean, standardDeviation) data
let maxv = Seq.fold max Int32.MinValue input
let minv = Seq.fold min Int32.MaxValue input
Seq.fold (fun (s1, s2) v -> 
  (max s1 v, min s2 v)) (Int32.MinValue, Int32.MaxValue) input
其中,输入是一组函数和一个序列,输出与上述函数相同

如果函数
mean
statardeviation
是黑匣子,并且我无法更改它们的实现,这是否可能


如果我自己写了
mean
standardDeviation
,有没有办法让它们一起工作?也许会以某种方式使它们不断地将输入输出到下一个函数,并在完成后将结果移交给它?

我们在这里讨论的是一个具有以下特征的函数:


(seq-seq->'b,f2:seq当函数为黑匣子时,仅使用一次迭代的唯一方法是使用
seq.cache
函数(该函数对序列求值一次并将结果存储在内存中)或将序列转换为其他内存表示形式

当一个函数以
seq
作为参数时,你甚至不能保证它只会对它进行一次计算——通常标准偏差的实现会首先计算平均值,然后再次迭代序列以计算误差平方


我不确定您是否可以仅通过一次传递计算标准偏差。但是,如果函数使用
fold
表示,则可以这样做。例如,使用两次传递计算最大值和平均值如下所示:

magicFunction (mean, standardDeviation) data
let maxv = Seq.fold max Int32.MinValue input
let minv = Seq.fold min Int32.MaxValue input
Seq.fold (fun (s1, s2) v -> 
  (max s1 v, min s2 v)) (Int32.MinValue, Int32.MaxValue) input
您可以使用如下所示的单程完成此操作:

magicFunction (mean, standardDeviation) data
let maxv = Seq.fold max Int32.MinValue input
let minv = Seq.fold min Int32.MaxValue input
Seq.fold (fun (s1, s2) v -> 
  (max s1 v, min s2 v)) (Int32.MinValue, Int32.MaxValue) input
lambda函数有点难看,但您可以定义一个组合器来组成两个函数:

let par f g (i, j) v = (f i v, g j v)
Seq.fold (par max min) (Int32.MinValue, Int32.MaxValue) input
这种方法适用于可以使用
fold
定义的函数,这意味着它们由一些初始值(
Int32.MinValue
在第一个示例中)和一些函数组成,这些函数用于在获得下一个值时更新初始(先前)状态(然后可能对结果进行一些后处理).一般来说,应该可以用这种方式重写单通函数,但我不确定是否可以对标准偏差进行重写。对于平均值,确实可以这样做:

let (count, sum) = Seq.fold (fun (count, sum) v -> 
  (count + 1.0, sum + v)) (0.0, 0.0) input
let mean = sum / count

事实上,可以使用
折叠计算标准偏差
-它使用方差的定义-例如,请参见“我不确定是否可以仅通过一次传递计算标准偏差”.看Knuth的《圣经》@JohnPalmer谢谢你的参考!@JonHarrop Knith的《圣经》的问题是,如果你乘坐easyJet飞机,你就不能把它放在20公斤的行李限额内。。。。