Reputation: 531
I have been trying to convert some C# to F# and it hasn't been going so good as I am relatively new to F#
Here is the working C# snippet:
static void doParallelForeach()
{
// The sum of these elements is 40.
int[] input = { 4, 1, 6, 2, 9, 5, 10, 3 };
int sum = 0;
Parallel.ForEach(
input,
() => 0,
(n, loopState, localSum) =>
{
localSum += n;
Console.WriteLine("Thread={0}, n={1}, localSum={2}", Thread.CurrentThread.ManagedThreadId, n, localSum);
return localSum;
},
(localSum) => Interlocked.Add(ref sum, localSum)
);
}
Here is the F# snippet that gives this compiler error: No overloads match for method 'ForEach'.
let doParallelForeach =
let input:int[] = [|4; 1; 6; 2; 9; 5; 10; 3|]
let sum = 0
Parallel.ForEach
(
input,
(fun ()-> 0),
(fun (n, loopState, localSum) ->
localSum += n
Console.WriteLine("Thread={0}, n={1}, localSum={2}", Thread.CurrentThread.ManagedThreadId, n, localSum);
return localSum),
(fun (localSum) -> Interlocked.Add(ref sum, localSum))
)
Can someone please explain what I am doing wrong?
Upvotes: 1
Views: 1323
Reputation: 55195
There are lots of problems with your code. Here's a literal translation:
let doParallelForeach() =
let input:int[] = [|4; 1; 6; 2; 9; 5; 10; 3|]
let sum = ref 0
Parallel.ForEach (
input,
(fun ()-> 0),
(fun n loopState localSum->
let localSum = localSum + n
Console.WriteLine("Thread={0}, n={1}, localSum={2}", Thread.CurrentThread.ManagedThreadId, n, localSum)
localSum),
(fun (localSum) -> Interlocked.Add(sum, localSum) |> ignore))
Notes:
doParallelForeach
into a function instead of a value of type unit
.return
and +=
aren't valid F# code. You don't need to use return
in F#, and you can only modify mutable values (and even then, there are no compound assignment operators). Instead, we just shadow localSum
with a new value.ref
incorrectly - it is a function in F#, not a modifier, and it is used to define new reference values, not to extract addresses to pass to methods. Furthermore, since sum
was a let-bound immutable value, you couldn't take its address anyway. The correct way to do this is to use F#'s ref
function to make sum
an instance of the int ref
type.fun n loopState localSum -> ...
instead of fun (n, loopState, localSum) -> ...
.Note that regardless of these fixes, this is a weird method - the results are kept in a local variable (sum
) which isn't ever exposed to the caller...
Upvotes: 7