# Summations and products in F#

I was bored, and looking to do something that involved anonymous functions, and it was suggested by @Quill, that I create a summation function. I decided to also include a product function as well to top the whole thing off.

For those who don't know, a summation is usually defined like this:

$$\sum_{n=a}^{b}f(n)$$

And a product is usually defined like this:

$$\prod_{n=a}^{b}f(n)$$

I'd like to know the following things:

• Am I doing this in a proper functional way?
• Is there a way to reduce the repetitiveness of the code?
• Is it okay to use List.fold to multiply all the elements of a list together? Is there a better way?
• Am I violation any style guidelines?
• Anything else?

Here's the code:

/// <summary>
/// Find the summation in a specific range, given
/// a specific function.
/// </summary>
let summation func low high =
let function_result_set: int list = [for x in low..high do yield x |> func]
let result = function_result_set |> List.sum
result

/// <summary>
/// Find the product in a specific range, given
/// a specific function.
/// </summary>
let product func low high =
let function_result_set: int list = [for x in low..high do yield x |> func]
let result = function_result_set |> List.fold (*) 1
result


And finally, here's a few tests:

[<EntryPoint>]
let main argv =
System.Console.WriteLine(summation (fun n -> n) 1 10)
System.Console.WriteLine(product (fun n -> n) 1 10)
0


And here's the desired output from the above tests:

55
3628800

• Are products like doing factorials the opposite way so it acts more like summation? – KingCodeFish Oct 14 '15 at 22:22
• @KingCodeFish A product is like a summation, except you're doing multiplication, rather than addition. – Ethan Bierlein Oct 14 '15 at 22:28
• @KingCodeFish Think of it like 1 * 2 * 3 .... 9 * 10 rather than 1 + 2 + 3 ... 9 + 10. – Ethan Bierlein Oct 14 '15 at 22:29
• Yes, I understand that. I was just wondering if it's like doing factorials backwards. – KingCodeFish Oct 14 '15 at 22:49
• @KingCodeFish No, I don't think so. – Ethan Bierlein Oct 14 '15 at 22:49

Starting with summation,

let summation func low high =
let function_result_set: int list = [for x in low..high do yield x |> func]
let result = function_result_set |> List.sum
result


First of all, we can remove result

let summation func low high =
let function_result_set: int list = [for x in low..high do yield x |> func]
function_result_set |> List.sum


Next, we don't need to construct a list containing func(low) .. func(high); we can instead operate over a sequence, meaning we don't have to have all those values in memory at once.

let summation func low high =
let function_result_set = Seq.map func { low .. high }
function_result_set |> Seq.sum


Now we can make it a bit more succinct

let summation func low high =
Seq.map func { low .. high } |> Seq.sum


Finally, we can make it more generic by using statically resolved type parameters. At the moment, if we have a call to summation like this:

printfn "%d" <| summation id 1 10


then summation will be constrained to be of type (int -> int) -> int -> int -> int. We can fix this by making the function inline:

let inline summation func low high =
Seq.map func { low .. high } |> Seq.sum


Now summation has type ('a -> 'b) -> 'a -> 'a -> 'b and the following code will compile:

printfn "%d" <| summation id 1 10
printfn "%f" <| summation id 1.0 10.0


Similar comments hold for product, but with two additional things:

• To make it generic we need to get the One property of the type ^a, and
• I've used the checked version of * to check for overflow
let inline product func low high : ^a =
Seq.map func { low .. high } |> Seq.fold Checked.(*) LanguagePrimitives.GenericOne< ^a >