gpt4 book ai didi

f# - 不带 for..in..do 的扩展计算表达式

转载 作者:行者123 更新时间:2023-12-03 11:01:16 26 4
gpt4 key购买 nike

我所说的扩展计算表达式是指具有通过 CustomOperation 定义的自定义关键字的计算表达式。属性。

阅读时 extended computation expressions ,我遇到了@kvb 的非常酷的 IL DSL:

let il = ILBuilder()

// will return 42 when called
// val fortyTwoFn : (unit -> int)
let fortyTwoFn =
il {
ldc_i4 6
ldc_i4_0
ldc_i4 7
add
mul
ret
}

我想知道如何在不使用 for..in..do 的情况下进行操作构造。我的直觉是它以 x.Zero 开头成员,但我还没有找到任何引用资料来验证这一点。

如果上面的例子太技术性,这里有一个类似的 DSL,其中列出了幻灯片的组件,但没有 for..in..do :
page {
title "Happy New Year F# community"
item "May F# continue to shine as it did in 2012"
code @"…"
button (…)
} |> SlideShow.show

我有几个密切相关的问题:
  • 如何在没有 For 的情况下定义或使用扩展计算表达式成员(即提供一个小的完整示例)?如果它们不再是 monad,我不会太担心,我对它们在开发 DSL 方面很感兴趣。
  • 我们可以在 let! 中使用扩展计算表达式吗?和 return! ?如果是,是否有任何理由不这样做?我问这些问题是因为我没有遇到任何使用 let! 的例子。和 return! .
  • 最佳答案

    很高兴您喜欢 IL 示例。了解表达式如何脱糖的最好方法可能是查看 spec (虽然它有点密集......)。

    在那里我们可以看到类似的东西

    C {
    op1
    op2
    }

    脱糖如下:
    T([<CustomOperator>]op1; [<CustomOperator>]op2, [], fun v -> v, true) ⇒
    CL([<CustomOperator>]op1; [<CustomOperator>]op2, [], C.Yield(), false) ⇒
    CL([<CustomOperator>]op2, [], 〚 [<CustomOperator>]op1, C.Yield() |][], false) ⇒
    CL([<CustomOperator>]op2, [], C.Op1(C.Yield()), false) ⇒
    〚 [<CustomOperator>]op2, C.Op1(C.Yield()) 〛[] ⇒
    C.Op2(C.Op1(C.Yield()))

    至于为什么 Yield()使用而不是 Zero ,这是因为如果作用域中有变量(例如,因为你使用了一些 lets ,或者在 for 循环中等),那么你会得到 Yield (v1,v2,...)但是 Zero显然不能这样使用。请注意,这意味着添加一个多余的 let x = 1进入托马斯的 lr示例将无法编译,因为 Yield将使用 int 类型的参数调用而不是 unit .

    还有一个技巧可以帮助理解计算表达式的编译形式,即(ab)使用 F# 3 中计算表达式的自动引用支持。只需定义一个什么都不做 Quote成员(member)和制作 Run只需返回其参数:
    member __.Quote() = ()
    member __.Run(q) = q

    现在您的计算表达式将评估为其脱糖形式的引用。这在调试时非常方便。

    关于f# - 不带 for..in..do 的扩展计算表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14110532/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com