1
votes

I have asked a related question here. I want to do a similar thing but this time thread an accumulator though the array of functions. I immediately thought of Array.Reduce or Array.Fold but they are not working for me:

let AddTen x =
    x + 10

let MultiplyFive x =
    x * 5

let SubtractTwo x =
    x - 2

let functionArray = [| AddTen; MultiplyFive; SubtractTwo |] 
let calculateAnswer functionArray x = functionArray |>Array.reduce(fun acc f -> f acc)

The last line throws this exception:

Type mismatch. Expecting a 'a -> 'b but given a 'b The resulting type would be infinite when unifying ''a' and ''b -> 'a'

Am I thinking about the problem incorrectly?

1
1) You're not using x. 2) Array.reduce has the signature ('T -> 'T -> 'T) -> 'T [] -> 'T, i.e. both arguments to your lambda must be the same type. Do you want Array.fold? - ildjarn
I couldn't figure it out with Array.fold either. I need to start with the input paramater and then invoke each function in turn using the output of the prior function as input into the next function - Jamie Dixon
Note that I can do it via functional composition and pipelining, I am just trying out a different way... - Jamie Dixon

1 Answers

2
votes

Take a look at these two:

let calculateReduce = functionArray |> Array.reduce (fun f g -> f >> g)
let calculateFold x = functionArray |> Array.fold (fun acc f -> f acc) x

In the reduce version, you take an array of functions and compose them into a single function which you can later call on x.

In the fold version you fold over the array of functions, threading the accumulator through and applying each function to it in sequence. x is the initial value of the accumulator here.

Your original code didn't work, because a reduce expects a 'a -> 'a -> 'a function, which in case of an array of functions would imply composition, while you were trying to apply one function of type int -> int to another.