F# 中的 Java 静态导入类似吗?

发布于 2024-11-29 14:24:28 字数 313 浏览 0 评论 0原文

来自 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

绻影浮沉 2024-12-06 14:24:28

在 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 或我自己有时冗长的模块名称执行此操作。

In Java, given a class mypackage.MyClass you can "statically import" all static members within that class using the declaration import static mypackage.MyClass.*. In F#, given the module MyNamespace.MyModule you can similarly make all functions within that module available without qualification using the declaration open MyNamespace.MyModule. But as Daniel pointed out, certain module are marked with the RequireQualifiedAccess 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 do let map = List.map.

Except, there is a good reason collection modules like List, Seq, and Array 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 allows map, for example, to be used on several different types without breaking type inference. Note that Seq is a bit special though in F# (and .NET), since it works on all types implementing the interface IEnumerable<'a> including lists and arrays. So you could alias let map = Seq.map and be able to work with map on all those collection types but you would lose features of those concrete implementations since IEnumerable<'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 like List, but I might do it for ResizeArray or perhaps my own sometimes long-winded module names.

情绪失控 2024-12-06 14:24:28

你可以这样做:

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

You can do something like:

let map = List.map
map (fun x -> 3*x) [1..10]
墨小沫ゞ 2024-12-06 14:24:28

通常,您可以通过使用 open TheModuleContainingTheFunction 来完全执行您想要的操作(无需限定条件即可使用函数)。标有 RequireQualifiedAccess 的模块除外属性。 ListSeqArray 具有此属性。

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

Usually, you can do exactly what you want--use a function without qualification--by using open TheModuleContainingTheFunction. The exceptions are modules marked with the RequireQualifiedAccess attribute. List, Seq, and Array 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 and List may be treated as Seq, which would seem to make many unqualified function calls ambiguous.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文