CinnamonBun
CinnamonBun

Reputation: 1150

What's the difference between type 'a list' and type List<int>

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

Answers (4)

phoog
phoog

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

Peter Ittner
Peter Ittner

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

Pavel Martynov
Pavel Martynov

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

Mat&#237;as Fidemraizer
Mat&#237;as Fidemraizer

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

Related Questions