3

I am working on some code where I need to use an f# query to sum a list.

For anyone who is working on f# basics, here's a handy link: https://learnxinyminutes.com/docs/fsharp/

So far, I have code that prints a statement for a sum of the square of 5 numbers.

So far, this correctly displays 3000 as the sum of the squares of each list. 'numbers' will be used for the query.

let square x = x * x
let numbers = [10.0; 20.0; 30.0; 40.0]

let sumOfSquare2 =
   [10.0; 20.0; 30.0; 40.0] 
   |> List.map square 
   |> List.sum 

printfn "Sum of square: %A" (sumOfSquare2)

let sumOfSquare = 
    List.sum ( List.map square [10.0; 20.0; 30.0; 40.0] )

printfn "Sum of square: %A" (sumOfSquare)

At the moment, I'm a little stuck on how to correctly use the 'square' function after the query.

// A query expression.

let query1 =
    query {
        for number in numbers do
            select (number)           
    }
   |> square query   


printfn "Query sum of squares: %A" (query1)

So how do I correctly present this? 'query' itself works (when using printfn on query) but when trying to pipeline the square function to query, it doesn't compile.

tristansokol
  • 4,054
  • 2
  • 17
  • 32

3 Answers3

2

It will be basically the same code you used with the list, but since the query returns a seq use Seq.map instead of List.map:

// A query expression.
let query1 =
    query {
        for number in numbers do
            select (number)           
    }
   |> Seq.map square    


printfn "Query sum of squares: %A" (query1)

Note that your query does not transform anything, but I think you did like this as an example.

Gus
  • 25,839
  • 2
  • 51
  • 76
  • Hello! Thank you very much. This worked nicely. Just wondering how I would then add the values of query1 (since this print statement returns each of the list values squared). Would this need to be pipelined in the query1 expression? – EidahageFeroe Mar 11 '17 at 06:31
  • 1
    @MichaelPotts that should be, again, the same as your initial example, just replace the list functions for the seq functions and it will work i.e. instead of ``List.sum`` use ``Seq.sum`` and so on. – Gus Mar 11 '17 at 07:41
1

Kindly note that, the query returns a sequence which you can iterate and then do your operation

Ex:

// Print results of a query
query1
|> Seq.map (fun customer -> printfn "Company: %s Contact: %s" customer.CompanyName customer.ContactName)

You can use it like:

query1 |> Seq.map (fun e -> square(e)) |> Seq.sum

Full Source Code

open System

// your code goes here
let square x = x * x
let numbers = [10.0; 20.0; 30.0; 40.0]

let query1 =
    query {
        for number in numbers do
            select (number)           
    } |> Seq.map square |> Seq.sum

Console.WriteLine(sprintf "%A" query1);

Try it

To learn more about the query, please go to https://learn.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/query-expressions

Saravanan
  • 7,637
  • 5
  • 41
  • 72
  • let query1 |> Seq.iter (fun e -> square(e)) |> Seq.sum results in a compilation error. I don't really know how to apply this to my own issue. I have read the article you linked. It does not fix the issue I am having which is applying my squared function to the result of query. – EidahageFeroe Mar 11 '17 at 04:34
  • Here's how I have understood your solution. This results in a compilation error. let query1 = query { for number in numbers do select (number) } |> Seq.iter (fun e -> square(query)) |> Seq.sum – EidahageFeroe Mar 11 '17 at 04:38
  • 1
    If you look at the function signature of `Seq.iter`, you will see that it returns unit, hence it's generally used for its side-effect (e.g. printing to screen). Indeed you want `Seq.map` and then `Seq.sum`. Queries return seq, which are lazy, so if you want to force it the evaluation just pipe it to Array: `|> Seq.toList` – s952163 Mar 11 '17 at 06:22
  • 1
    sorry, that should be a map instead of iter... fixed it – Saravanan Mar 11 '17 at 10:58
1

F# supports summing within the query, so you can just do this to get the sum of the squares:

query {
    for num in numbers do
    sumBy (square num)
}
kvb
  • 54,864
  • 2
  • 91
  • 133