F#中的AutoOpen属性

nic*_*las 28 f# code-organization

使用AutoOpen属性的推荐原则是什么?

(这个问题可能是在类似命名类型上何时使用模块功能VS静态功能的延续)

专家F#指出"当你定义ad hoc顶级运算符和函数时,这可能很有用:"

因此,这似乎可以减少代码组织中的模块角色,当您在技术上需要编写代码但从客户端角度删除它的存在时.

还有别的吗?你什么时候使用它?

Tom*_*cek 40

我认为该AutoOpen属性的主要用途是当您的库用户打开命名空间时,您想要使一些自由绑定值可用.这是属性非常有用的地方,因为我认为库通常应该在命名空间中导出所有定义,但出于某些目的,您需要导出值,并且不能在命名空间内定义值.

以下是来自F#异步扩展的示例,它定义了计算构建器,因此需要导出asyncSeq值(但同时,所有功能都包含在命名空间中):

namespace FSharp.Async

type AsyncSeq<'T> = (* ... *)
type AsyncSeqBuilder() = (* ... *)

[<AutoOpen>]
module GlobalValues = 
  let asyncSeq = AsyncSeqBuilder()
Run Code Online (Sandbox Code Playgroud)

图书馆的用户可以写作open FSharp.Async,他们会看到asyncSeq.我认为相同的模式用于各种数学库(您还希望导出简单命名的函数.)

对于模块(例如ListSeq),我认为大多数人不会open通过模块名称(例如List.map)使用和访问函数,所以尽管你可以将它用于嵌套模块,但我没有经常看到它.


Dan*_*iel 20

它可用于将模块组织到子模块中,但在外部呈现统一/单模块视图:

module Outer =

  [<AutoOpen>]
  module Inner1 =
    let f1() = ()

  [<AutoOpen>]
  module Inner2 =
    let f2() = ()

open Outer

let x = f1()
let y = f2()
Run Code Online (Sandbox Code Playgroud)

FParsec做到这一点:open FParsec打开所有子模块(Primitives,CharParsers,等).