F#:有没有办法扩展 monad 关键字列表?

发布于 2025-01-05 10:28:30 字数 1073 浏览 1 评论 0原文

在 F# monad 中,如果您说 let!,编译器会将其转换为您在 monad 构建器上定义的 Bind 成员。

现在我看到有查询单子,如 所示在 MSDN 上,您可以在其中说:

query {
    for student in db.Student do
    select student
    count
}

selectcount 例如,将被翻译为 QueryBuilder 成员<一href="https://msdn.microsoft.com/visualfsharpdocs/conceptual/querybuilder.select%5B%27t%2C%27q%2C%27result%5D-method-%5Bfsharp%5D" rel="noreferrer">Linq。 QueryBuilder.Select 和 Linq.QueryBuilder .计数

我的问题是,关键字到成员的映射是硬连线到 F# 编译器中的,还是可扩展的?例如,我可以这样说:

FooMonadBuilder() {
    bar
}

并以某种方式告诉 F# 编译器 bar 映射到 FooMonadBuilder.Bar() 方法吗?

Inside an F# monad, if you say let!, the compiler translates that to a Bind member that you've defined on the monad builder.

Now I see there are Query monads, as shown here on MSDN, where you can say:

query {
    for student in db.Student do
    select student
    count
}

and the select and count, for example, will be translated to the QueryBuilder members Linq.QueryBuilder.Select and Linq.QueryBuilder.Count.

My question is, is this mapping of keywords to members hardwired into the F# compiler, or is it extensible? For example, can I say something like:

FooMonadBuilder() {
    bar
}

and somehow tell the F# compiler that bar maps to a FooMonadBuilder.Bar() method?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(2

半步萧音过轻尘 2025-01-12 10:28:30

在 F# 2.0(即 Visual Studio 2010)中,无法扩展关键字列表(Ramon 的扩展除外)。但是,F# 3.0 (Visual Sutdio 11) 中的查询机制是可扩展的,您可以定义自己的关键字,类似于 selectcount

下面是一个基本示例,它使用 reverse 关键字定义了诸如 seq 构建器之类的内容:

type SeqBuilder() =
    // Standard definition for 'for' and 'yield' in sequences
    member x.For (source : seq<'T>, body : 'T -> seq<'R>) =
      seq { for v in source do yield! body v }
    member x.Yield item =
      seq { yield item }

    // Define an operation 'select' that performs projection
    [<CustomOperation("select")>]
    member x.Select (source : seq<'T>, [<ProjectionParameter>] f: 'T -> 'R) : seq<'R> =
        Seq.map f source

    // Defines an operation 'reverse' that reverses the sequence    
    [<CustomOperation("reverse", MaintainsVariableSpace = true)>]
    member x.Expand (source : seq<'T>) =
        List.ofSeq source |> List.rev

let mseq = SeqBuilder()

其工作原理的详细信息尚未记录,但有 CustomOperation 属性表示该操作应被视为特殊语法(您可以设置各种属性来指定其行为方式 - MaintainsVariableSpace 意味着它不会更改序列内的值)。 Projectionparameter 属性指定关键字后面的表达式应隐式转换为函数。

现在,mseq 构建器支持 selectreverse

let q = mseq { for i in 1 .. 10 do
               select (i + 100)
               reverse }

In F# 2.0 (that is Visual Studio 2010), there is no way to extend the keyword list (other than Ramon's extension). However, the query mechanism in F# 3.0 (Visual Sutdio 11) is extensible and you can define your own keywords similar to select and count.

Here is a basic example that defines something like seq builder with reverse keyword:

type SeqBuilder() =
    // Standard definition for 'for' and 'yield' in sequences
    member x.For (source : seq<'T>, body : 'T -> seq<'R>) =
      seq { for v in source do yield! body v }
    member x.Yield item =
      seq { yield item }

    // Define an operation 'select' that performs projection
    [<CustomOperation("select")>]
    member x.Select (source : seq<'T>, [<ProjectionParameter>] f: 'T -> 'R) : seq<'R> =
        Seq.map f source

    // Defines an operation 'reverse' that reverses the sequence    
    [<CustomOperation("reverse", MaintainsVariableSpace = true)>]
    member x.Expand (source : seq<'T>) =
        List.ofSeq source |> List.rev

let mseq = SeqBuilder()

The details how this works are not yet documented, but the CustomOperation attribute says that the operation should be treated as a special syntax (you can set various properties to specify how it behaves - MaintainsVariableSpace means that it does not change the values inside sequence). The Projectionparameter attribute specifies that the expression following the keyword should be implicitly converted to a function.

Now, the mseq builder supports both select and reverse:

let q = mseq { for i in 1 .. 10 do
               select (i + 100)
               reverse }
我很坚强 2025-01-12 10:28:30

简短的回答:不。

我已经扩展了编译器来支持这一点,欢迎您阅读我的博客文章 http://ramon.org.il/wp/2011/04/take-computation-expressions-one-step-further/

Short answer: no.

I've extended the compiler to support that, you're welcome to read my blog article http://ramon.org.il/wp/2011/04/taking-computation-expressions-one-step-further/

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