F# Func type inference difference between Seq and PSeq ToDictionary

只谈情不闲聊 提交于 2019-12-01 16:38:54

I believe that this is not exactly a bug, but merely a very ugly corner case of F#'s type inference algorithm where overloads and type directed conversions are involved. Oddly, the compiler infers the ad2 binding's type correctly because there's a second overload of ToDictionary that has two arguments, which causes an additional overload resolution step during inference. On the other hand, there is only a single overload with three arguments, so the overload resolution step isn't used when trying to infer ad's type.

As I mentioned, the other piece of the puzzle is the type directed conversion from an F# function to a .NET delegate type (this is how you can pass an F# function where a Func<_,_> is expected). Basically, if you use an explicit lambda or if there are multiple overloads, then this conversion is considered, but if there is only a single overload and no explicit lambda then the conversion isn't considered. This means that the following will also work:

let ad3 = a.ToDictionary(System.Func<_,_>(fst), 
                         System.Func<_,_>(snd), HashIdentity.Structural)

because now there's no need to perform a type directed conversion.

This result is certainly counterintuitive, so I'd hope that there is some way to tweak the type inference algorithm to better handle these corner cases. Unfortunately, interoperating with certain aspects of the .NET type system (such as named delegate types, subtyping, overloading, etc.) makes inference much harder than it might otherwise be, and there may be some reason that the algorithm can't easily be modified to handle this case.

Looks like a bug (or an overload resolution edge case), but you can avoid the issue by using the built-in dict function:

let a = Seq.singleton (1,"a")  
let b = a |> PSeq.map id 
let bd = dict b
let ad = dict a
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!