F# 中的 Java 静态导入类似吗?
来自 Haskell,我想知道是否有一种方法可以避免每次我想使用 map
时都必须编写完整的 List.map
。
有没有像Java的静态导入之类的东西,让我只能写map
?
回顾一下:
我目前必须写:
List.map (fun -> 3*x) [1..10]
但是,我希望能够写
map (fun -> 3*x) [1..10]
谢谢
Coming from Haskell, I'd like to know if there is a way to avoid having to write the full List.map
every time I want to use a map
.
Is there anything such as Java's static imports, so that I can only write map
?
To recap:
I currently have to write:
List.map (fun -> 3*x) [1..10]
yet, I'd like to be able to write
map (fun -> 3*x) [1..10]
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在 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
之类的操作。除此之外,像
List
、Seq
和Array
这样的集合模块都需要限定访问,这是有充分理由的:它们都有一组相似的函数仅作用于其类型,F# 使用此信息进行类型推断。我不确定细节,但 Haskell 在其类型系统中具有一些功能,例如,它允许在多种不同类型上使用map
而不会破坏类型推断。请注意,Seq
在 F#(和 .NET)中有点特殊,因为它适用于实现接口IEnumerable<'a>
的所有类型,包括列表和数组。因此,您可以使用let map = Seq.map
别名,并能够在所有这些集合类型上使用map
,但您会失去这些具体实现的功能,因为IEnumerable< ;'a>
是其中的最小公分母。因此,最终,在 F# 中,最好的办法就是在每个集合模块中使用完全限定的
map
函数。对于你得到的类型推断来说,这是一个很小的代价(我有时想知道,我是否可以通过类型推断来节省我因限定所有这些集合函数而失去的东西,但我相信你最终会通过类型推断节省而获胜,尤其是)当考虑复杂的通用签名时,也许更重要的是必须通过所有这些类型计算进行推理)。保存击键的另一种选择是通过模块别名。您可以执行类似
module L = List
的操作。我不会对List
这样的简短、常见的模块名称执行此操作,但我可能会对ResizeArray
或我自己有时冗长的模块名称执行此操作。In Java, given a class
mypackage.MyClass
you can "statically import" all static members within that class using the declarationimport static mypackage.MyClass.*
. In F#, given the moduleMyNamespace.MyModule
you can similarly make all functions within that module available without qualification using the declarationopen MyNamespace.MyModule
. But as Daniel pointed out, certain module are marked with theRequireQualifiedAccess
attribute which forbids this.However, you can still alias specific functions within a module similar to how you can statically import specific static members of a class in Java. For example, in Java, you can do something like
static import mypackage.MyClass.myMethod
and in F# you can dolet map = List.map
.Except, there is a good reason collection modules like
List
,Seq
, andArray
all require qualified access: they all have a similar set of functions which only act on their types and F# uses this information for its type inference. I'm not sure of the details but Haskell has some feature in its type system which allowsmap
, for example, to be used on several different types without breaking type inference. Note thatSeq
is a bit special though in F# (and .NET), since it works on all types implementing the interfaceIEnumerable<'a>
including lists and arrays. So you could aliaslet map = Seq.map
and be able to work withmap
on all those collection types but you would lose features of those concrete implementations sinceIEnumerable<'a>
is the lowest common denominator among them.So in the end, in F#, the best thing to do is just use the fully qualified
map
functions in each collection module. It's a small price to pay for the type inference you get in return (I sometimes wonder if I save in typing through type inference what I lose having to qualify all those collection functions, but I believe you win in the end through type inference savings especially when considering complex generic signatures and perhaps more importantly having to reason through all those type calculations).One more option for saving key strokes is through module aliases. You can do something like
module L = List
. I wouldn't do this for short, common module names likeList
, but I might do it forResizeArray
or perhaps my own sometimes long-winded module names.你可以这样做:
You can do something like:
通常,您可以通过使用
open TheModuleContainingTheFunction
来完全执行您想要的操作(无需限定条件即可使用函数)。标有RequireQualifiedAccess
的模块除外属性。List
、Seq
和Array
具有此属性。我怀疑这些需要限定,因为它们有许多具有相同名称的函数(
map
、iter
等),并且它们处理的类型之间存在多态关系,即Array
和List
可能会被视为Seq
,这似乎会使许多不合格的函数调用变得不明确。Usually, you can do exactly what you want--use a function without qualification--by using
open TheModuleContainingTheFunction
. The exceptions are modules marked with theRequireQualifiedAccess
attribute.List
,Seq
, andArray
have this attribute.I suspect these require qualification because they have many functions with the same names (
map
,iter
, etc) and there is a polymorphic relationship between the types they deal with, i.e.,Array
andList
may be treated asSeq
, which would seem to make many unqualified function calls ambiguous.