来自 Haskell,我想知道是否有办法避免编写完整的 List.map
每次我想使用 map
.
有没有Java的静态导入之类的,所以只能写map
?
回顾一下:
我目前必须写:
List.map (fun -> 3*x) [1..10]
然而,我希望能够写作
map (fun -> 3*x) [1..10]
谢谢
最佳答案
在 Java 中,给定一个类 mypackage.MyClass
您可以使用声明import static mypackage.MyClass.*
“静态导入”该类中的所有静态成员.在 F# 中,给定模块 MyNamespace.MyModule
类似地,您可以使用声明 open MyNamespace.MyModule
使该模块中的所有功能无需限定即可使用。 .但正如丹尼尔指出的那样,某些模块标有 RequireQualifiedAccess
禁止这一点的属性。
但是,您仍然可以为模块中的特定函数起别名,类似于在 Java 中静态导入类的特定静态成员的方式。例如,在 Java 中,您可以执行类似 static import mypackage.MyClass.myMethod
的操作。在 F# 中,您可以执行 let map = List.map
.
除了,有一个很好的理由收集模块,如 List
, Seq
, 和 Array
都需要合格的访问:它们都有一组相似的函数,只作用于它们的类型,F# 使用这些信息进行类型推断。我不确定细节,但 Haskell 在其类型系统中有一些特性,它允许 map
,例如,在不破坏类型推断的情况下用于几种不同的类型。请注意 Seq
虽然在 F#(和 .NET)中有点特殊,因为它适用于实现接口(interface) IEnumerable<'a>
的所有类型包括列表和数组。所以你可以别名 let map = Seq.map
并能够与 map
合作在所有这些集合类型上,但您将失去这些具体实现的功能 IEnumerable<'a>
是其中最小的公分母。
所以最后,在 F# 中,最好的办法就是使用完全限定的 map
每个收集模块中的功能。为您获得的类型推断付出的代价很小(我有时想知道我是否通过类型推断节省了键入所有这些集合函数所失去的东西,但我相信您最终会通过类型推断节省特别是在考虑复杂的通用签名时,也许更重要的是必须通过所有这些类型计算进行推理)。
保存击键的另一种选择是通过模块别名。您可以执行 module L = List
之类的操作.对于像 List
这样的简短通用模块名称,我不会这样做。 , 但我可能会为 ResizeArray
或者也许是我自己有时冗长的模块名称。
关于.net - 像 Java 在 F# 中的静态导入一样吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7054451/