val a: seq let b = -6ren">
gpt4 book ai didi

F# Func 类型推断 Seq 和 PSeq ToDictionary 的区别

转载 作者:行者123 更新时间:2023-12-04 10:54:31 26 4
gpt4 key购买 nike

给定一个简单的元组序列,以及一个使用 F# PowerPack 的 PSeq 的并行序列:

let a = Seq.singleton (1,"a")  --> val a: seq<int * string>
let b = a |> PSeq.map id --> val b: pseq<int * string>

现在我想从他们创建一个 .Net BCL 字典:
let bd = b.ToDictionary(fst, snd, HashIdentity.Structural)
let ad = a.ToDictionary(fst, snd, HashIdentity.Structural)
let ad2 = a.ToDictionary(fst, snd)
let ad3 = a.ToDictionary((fun (x,y) -> x), (fun (x,y) -> y), HashIdentity.Structural)

let bd作品, let ad无法编译,因为它无法正确推断类型并转换为 BCL 的 Func。有趣的是,如果我省略第三个参数,它就可以正常工作,如 let ad2 ,或者如果我写出 fstsnd手动内联,如 let ad3 .

This expression was expected to have type Func<(int * string),'a> but here has type 'b * 'c -> 'b


  • 为什么let ad不编译,而所有替代方案都可以正常工作?
  • 有没有办法制作let ad编译,不提供内联函数或类型注释?

  • PS:我需要 HashIdentity.Structural 因为在实际代码中,键不是整数,而是元组或记录

    更新:我现在定义了 let dictionary (s : ('a * 'b) seq) = s.ToDictionary((fun (x,y)->x), (fun (x,y)->y), HashIdentity.Structural)所以我可以写 let ad = a |> dictionary ,但我仍然对为什么它不能用 fst 编译感兴趣和 snd职能。

    最佳答案

    我相信这并不完全是一个错误,而只是 F# 类型推断算法的一个非常丑陋的极端案例,其中涉及重载和类型定向转换。奇怪的是,编译器推断出 ad2绑定(bind)的类型正确,因为有第二个重载 ToDictionary有两个参数,这会在推理过程中导致额外的重载解析步骤。另一方面,只有一个带有三个参数的重载,因此在尝试推断 ad 时不使用重载解析步骤。的类型。

    正如我所提到的,难题的另一部分是从 F# 函数到 .NET 委托(delegate)类型的类型定向转换(这是您如何在预期 Func<_,_> 的地方传递 F# 函数的方法)。基本上,如果您使用显式 lambda 或有多个重载,则考虑此转换,但如果只有一个重载且没有显式 lambda,则不考虑转换。这意味着以下内容也将起作用:

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

    因为现在不需要执行类型定向转换。

    这个结果肯定是违反直觉的,所以我希望有一些方法可以调整类型推断算法以更好地处理这些极端情况。不幸的是,与 .NET 类型系统的某些方面(例如命名的委托(delegate)类型、子类型化、重载等)进行互操作会使推理变得比其他方式困难得多,并且可能有一些原因导致算法不容易修改以处理这种情况。

    关于F# Func 类型推断 Seq 和 PSeq ToDictionary 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12933366/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com