Reputation: 1150
I'm new to F# and I seem to be having an issue getting the sum of a list.
let listOne = [1 .. 10]
let listTwo = listOne.Select(fun i -> i * 2).ToList()
let result = List.sum listTwo
result.Dump()
However, the following code produces this error:
This expression was expected to have type 'a list but here has type List<int>
Any insight as to why they are different would be greatly appreciated
Upvotes: 1
Views: 430
Reputation: 43046
Matias Fidemraizer explained the problem nicely, but it's possible to resolve your problem more idiomatically in F#, without using Linq at all. Instead of Select
and ToList
, use the F# map
function in the List
module:
let listOne = [1 .. 10]
let listTwo = List.map (fun i -> i * 2) listOne
let result = List.sum listTwo
You could also do this all in one go, using the pipe operator:
let result = [1 .. 10] |> List.map (fun i -> i * 2) |> List.sum
You can also use partial function application instead of the fun
keyword:
let result = [1 .. 10] |> List.map ((*) 2) |> List.sum
You can also use the sumBy function and save yourself from creating a second list in memory:
let result = [1 .. 10] |> List.sumBy ((*) 2)
Upvotes: 0
Reputation: 551
Like already posted the Problem is that F# has its own List-Type which supports all the pipelining stuff etc.
To convert a .NET-List or IEnumerable that you get by the use of Linq into a F#-List you can use List.ofSeq
or List.ofArray
like the following:
let listOne = [1 .. 10]
let listTwo = listOne.Select(fun i -> i * 2).ToList()
let result = List.sum (List.ofSeq listTwo)
Upvotes: 0
Reputation: 560
let listOne = [1 .. 10]
let listTwo = listOne.Select(fun i -> i * 2).ToList()
listOne : int list (alias for Microsoft.FSharp.Collections.List<int>) listTwo : System.Collections.Generic.List<int>
As you can see, listOne and listTwo have totally different types.
Upvotes: 1
Reputation: 64933
F# integer lists aren't List<T>
(i.e. List<int>
).
This is why it throws such error: List<T>
isn't a FSharpList<T>
When you call IEnumerable<T>.Select
you're converting FSharpList<int>
into IEnumerable<int>
, then IEnumerable<T>.ToList()
returns a List<int>
.
Furthermore, you should use IEnumerable<T>.Sum(...)
:
let result = listTwo.Sum();
Also, you won't need to convert the IEnumerable<int>
into List<int>
: .Sum(...)
is a member of IEnumerable<T>
interface.
Upvotes: 4