Apply multiple aggregate functions with one enumeration

Suppose I have a number of functions that work on a sequence, and I want to use them together as follows:

let meanAndStandardDeviation data = 
    let m = mean data
    let sd = standardDeviation data
    (m, sd)

The code above will list the sequence twice. I am interested in a function that will give the same result, but list the sequence only once. This function will look something like this:

magicFunction (mean, standardDeviation) data

where the input is a set of functions, and the sequence and output coincide with the above function.

Is it possible if the functions meanand stadardDeviationare black cells, and I can not change their implementation?

If I wrote meanit standardDeviationmyself, is there a way to get them to work together? Maybe somehow make them continue to enter input into the next function and pass the result when they are done?

+3
source share
2 answers

The only way to do this using only one iteration when the functions are black boxes is to use a function Seq.cache(which evaluates the sequence once and stores the results in memory) or convert the sequence to another, memory representation.

seq<T> , , , , .

, . , fold. , :

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

- , :

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
+3

:

(seq<'a> -> 'b) * (seq<'a> -> 'c) -> seq<'a> -> ('b * 'c)

, , , , . , , :

let magicFunc (f1:seq<'a>->'b, f2:seq<'a>->'c) (s:seq<'a>) = 
    let cached = s |> Seq.cache
    (f1 cached, f2 cached)

(, ), , , . . - ? ?

+2

All Articles