像F#中的Java静态导入一样?

时间:2011-08-14 01:41:04

标签: .net f# functional-programming

来自Haskell,我想知道每次我想使用List.map时是否有办法避免编写完整的map

是否存在Java的静态导入,因此我只能编写map

回顾一下:

我目前要写:

List.map (fun -> 3*x) [1..10]

然而,我希望能够写

map (fun -> 3*x) [1..10]

由于

3 个答案:

答案 0 :(得分:9)

在Java中,给定一个类mypackage.MyClass,您可以使用声明import static mypackage.MyClass.*“静态导入”该类中的所有静态成员。在F#中,给定模块MyNamespace.MyModule,您可以类似地使用声明open MyNamespace.MyModule无限制地使该模块中的所有函数可用。但正如Daniel指出的那样,某些模块标有RequireQualifiedAccess属性,禁止这样做。

但是,您仍然可以在模块中对特定函数进行别名,类似于在Java中静态导入类的特定静态成员的方式。例如,在Java中,您可以执行类似static import mypackage.MyClass.myMethod的操作,而在F#中可以执行let map = List.map

除此之外,有一个很好的理由,例如ListSeqArray等收集模块都需要合格访问权限:它们都有一组类似的功能,只对其类型起作用和F#使用此信息进行类型推断。我不确定细节,但Haskell在其类型系统中有一些功能,例如,允许map在不破坏类型推断的情况下用于几种不同的类型。请注意Seq在F#(和.NET)中有点特殊,因为它适用于实现接口IEnumerable<'a>的所有类型,包括列表和数组。所以你可以别名let map = Seq.map并且能够在所有这些集合类型上使用map但是你会失去那些具体实现的功能,因为IEnumerable<'a>是其中最低的共同点。

所以最后,在F#中,最好的办法就是在每个集合模块中使用完全限定的map函数。你得到的类型推断是一个很小的代价(我有时会想知道我是否通过类型推断来节省我输入的所有这些收集功能的资格,但我相信你最终会通过类型推理节省而获胜在考虑复杂的通用签名时,或许更重要的是必须推理所有这些类型的计算)。

保存击键的另一个选项是通过模块别名。您可以执行module L = List之类的操作。对于像List这样的简短常见模块名称,我不会这样做,但我可能会为ResizeArray执行此操作,或者可能是我自己有时冗长的模块名称。

答案 1 :(得分:4)

您可以执行以下操作:

let map = List.map
map (fun x -> 3*x) [1..10]

答案 2 :(得分:3)

通常,您可以使用open TheModuleContainingTheFunction完全按照自己的意愿行事 - 使用无资格的功能。例外是标有RequireQualifiedAccess属性的模块。 ListSeqArray具有此属性。

我怀疑这些需要限定,因为它们有许多具有相同名称的函数(mapiter等),并且它们处理的类型之间存在多态关系,即{{1并且Array可能会被视为List,这似乎会使许多不合格的函数调用变得模棱两可。