Franco Tiveron
Franco Tiveron

Reputation: 2896

F# - using Linq SelectMany on dictionary doesn't work as expected

I expected the two following snippets to both work, but the F# one fails to find an overload for SelectMany

//C#
var aaa = new Dictionary<string, List<string>>();
Func<KeyValuePair<string, List<string>>, List<string>> fff = (KeyValuePair<string, List<string>> kvp) => kvp.Value;
var bbb = aaa.SelectMany(fff);

//F#
let aaa = new Dictionary<string, List<string>>()
let fff = Func<_, _>(fun (kvp:KeyValuePair<string, List<string>>) -> kvp.Value)
let bbb = aaa.SelectMany(fff) //Error   FS0041  No overloads match for method 'SelectMany'

Does anyone know why? Notice that fff have the same type in both snippets

Upvotes: 0

Views: 137

Answers (2)

Franco Tiveron
Franco Tiveron

Reputation: 2896

My question is about "why" not "how". the other answers gave the solution indirectly, however the answer to the original question is like:

" SelectMany expects a function returning IEnumerable<>, while fff returns List<>. C# allows using fff directly by implicitly cast, F# is stricter and requires an explicit cast"

Upvotes: 0

Brian Berns
Brian Berns

Reputation: 17038

It looks like F# requires you to explicitly cast the return type to IEnumerable<_>, so this will work:

let aaa = new Dictionary<string, List<string>>()
let fff = Func<_, _>(fun (kvp:KeyValuePair<string, List<string>>) -> kvp.Value :> IEnumerable<_>)
let bbb = aaa.SelectMany(fff)

Or, more simply:

let aaa = new Dictionary<string, List<string>>()
let bbb = aaa.SelectMany(fun kvp -> kvp.Value :> IEnumerable<_>)

However, as mentioned above, using the Seq module instead of LINQ is much more idiomatic in F#.

Upvotes: 2

Related Questions