如何编写一个计算表达式生成器来累积值并允许标准语言构造?

2024-05-21

我有一个计算表达式生成器,可以随时生成值,并且有许多自定义操作。但是,它不允许标准 F# 语言构造,并且我在弄清楚如何添加此支持方面遇到了很多麻烦。

举一个独立的例子,下面是一个非常简单且毫无意义的构建 F# 列表的计算表达式:

type Items<'a> = Items of 'a list

type ListBuilder() =
    member x.Yield(()) = Items []

    [<CustomOperation("add")>]
    member x.Add(Items current, item:'a) =
        Items [ yield! current; yield item ]

    [<CustomOperation("addMany")>]
    member x.AddMany(Items current, items: seq<'a>) =
        Items [ yield! current; yield! items ]

let listBuilder = ListBuilder()

let build (Items items) = items

我可以用它来构建列表:

let stuff =
    listBuilder {
        add 1
        add 5
        add 7
        addMany [ 1..10 ]
        add 42
    } 
    |> build

然而,这是一个编译器错误:

listBuilder {
    let x = 5 * 39
    add x
}

// This expression was expected to have type unit, but
// here has type int.

这也是:

listBuilder {
    for x = 1 to 50 do
        add x
}

// This control construct may only be used if the computation expression builder
// defines a For method.

我已经阅读了我能找到的所有文档和示例,但有些东西我没有得到。每一个.Bind() or .For()我尝试的方法签名只会导致越来越多令人困惑的编译器错误。我可以找到的大多数示例要么在您进行过程中建立一个值,要么允许常规的 F# 语言构造,但我还没有找到一个能够同时完成这两者的示例。

如果有人可以通过向我展示如何采用此示例并在构建器中添加支持来为我指明正确的方向let绑定和for循环(至少 -using, while and try/catch那就太好了,但如果有人让我开始,我可能可以弄清楚这些),然后我将能够感激地将课程应用于我的实际问题。


最好看的地方是spec http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec.html#_Toc335818835。例如,

b {
    let x = e
    op x
}

被翻译成

   T(let x = e in op x, [], fun v -> v, true)
=> T(op x, {x}, fun v -> let x = e in v, true)
=> [| op x, let x = e in b.Yield(x) |]{x}
=> b.Op(let x = e in in b.Yield(x), x)

因此,这表明了问题所在,尽管它没有提供明显的解决方案。清楚地,Yield需要泛化,因为它需要采用任意元组(基于范围内的变量数量)。也许更微妙的是,它还表明x不在调用范围内add(请参阅未绑定的x作为第二个参数b.Op?)。为了允许您的自定义运算符使用绑定变量,它们的参数需要具有[<ProjectionParameter>]属性(并从任意变量中获取函数作为参数),并且您还需要设置MaintainsVariableSpace to true如果您希望绑定变量可供以后的操作员使用。这会将最终翻译更改为:

b.Op(let x = e in b.Yield(x), fun x -> x)

由此看来,似乎没有办法避免在每个操作之间传递一组绑定值(尽管我很想被证明是错误的)——这将需要您添加一个Run方法在最后删除这些值。将它们放在一起,您将得到一个如下所示的构建器:

type ListBuilder() =
    member x.Yield(vars) = Items [],vars

    [<CustomOperation("add",MaintainsVariableSpace=true)>]
    member x.Add((Items current,vars), [<ProjectionParameter>]f) =
        Items (current @ [f vars]),vars

    [<CustomOperation("addMany",MaintainsVariableSpace=true)>]
    member x.AddMany((Items current, vars), [<ProjectionParameter>]f) =
        Items (current @ f vars),vars

    member x.Run(l,_) = l
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何编写一个计算表达式生成器来累积值并允许标准语言构造? 的相关文章

随机推荐

  • java.lang.ArrayStoreException:迁移到 Android Annotations v.2.7 后的 sun.reflect.annotation.TypeNotPresentExceptionProxy

    迁移到 Android Annotations v 2 7 后 我在 Eclipse 中构建项目时遇到了问题 同时 Maven 构建没问题 这是来自 eclipse 错误日志的堆栈跟踪 Error Mon Nov 05 15 49 49 G
  • 如何在 React 组件测试中使用 data-testid 属性?

    我正在对一个简单的反应组件进行组件测试 我想渲染该组件 然后对其进行一些测试 问题是cy get 似乎没有找到基于的组件data testid属性 我用一个简单的方法测试了它div和div能找到就好了 我在检查时也注意到DOM在 cypre
  • 在 swift 中获取 NSImage 的 PNG 表示

    嘿 我在获取 NSImage 对象的 PNG 表示时遇到了一些问题 这就是我正在做的 var imgData NSData coverImgView image TIFFRepresentation var bitmap NSBitmapI
  • 如何消除禁用的 UIButton 的灰色外观

    我有一个 UIButton 我希望它处于禁用状态时与处于正常状态时看起来完全相同 现在它看起来有点灰色 不要使用enabled属性或setEnabled NO方法 而是使用 myButton setUserInteractionEnable
  • 无法更改 SVG 元素的类名

    我想通过单击按钮来更改应用于 SVG 的类 代码是here http jsfiddle net p19rnmev 我的 SVG 看起来像
  • NodeJs 永远无法在 ubuntu 服务器中工作

    我安装了forever https www npmjs org package forever作为超级用户在我的 ubuntu 服务器中全局使用 npm 模块 但我无法使用它启动我的nodeJs 应用程序 我在终端中输入 永远 但似乎没有执
  • 保存 JPA 实体时出现 java.lang.StackOverflowError

    我正在使用 Spring JPA 将实体保存到数据库中 下面是代码结构 客户 java Entity Table name customer Data public class Customer Id GeneratedValue stra
  • 如何在Word 2010中从SQL数据库检索数据?

    我想用 MS SQL 数据库中的数据填充 Word 文档 这可能吗 如果可能的话 如何实现 我过去曾通过多种方式做到这一点 这取决于用户是从 Microsoft Word 外部还是从 Microsoft Word 内部启动操作 From I
  • 除 .spec.js 之外的每个 .js 文件的节点 glob 模式

    我正在寻找更好的全局模式以供使用 我想找到所有 js文件但排除 spec js文件 到目前为止我有以下解决方案 我目前拥有的解决方案要求我不断添加文件扩展名以排除它们 否则它们会被拾取 例如 html files 我试图让它只寻找 js文件
  • Flume将数据从MySQL迁移到Hadoop

    请分享您的想法 需求是将MySQL db中的数据迁移到Hadoop HBase进行分析 数据应该实时或接近实时地迁移 Flume可以支持这个吗 有什么更好的方法 据我了解 Flume 并不是为此而设计的 Flume 基本上用于读取日志 如数
  • 创建可重用的 WINDOW 控件

    好吧 这似乎很难 或者我错过了一些明显的东西 我想创建可重复使用的 WINDOW 它将在所有产品中使用 这意味着该控件位于 WPF Controls 程序集中 Themes Generic xaml 不是一个解决方案 我需要为窗口提供自己的
  • 是否可以创建一个脚本来保存和恢复权限?

    我正在使用 Linux 系统 需要对一组嵌套文件和目录进行一些权限实验 我想知道是否没有某种方法可以保存文件和目录的权限 而不保存文件本身 换句话说 我想保存权限 编辑一些文件 调整一些权限 然后将权限恢复到目录结构中 将更改的文件保留在适
  • OpenJDK 源代码中如何以及在何处解释分配堆内存?

    我正在尝试更改我的研究项目的 OpenJDK 源代码 我想知道在 Java 程序中调用 new 运算符时的代码流程 class MyFirstProgram public static void main String args throw
  • 依赖属性回调不起作用

    我有以下代码 private static readonly DependencyProperty IDProperty DependencyProperty Register ID typeof int typeof DetailData
  • 带有 Rake 的 RubyMine 调试器?

    使用 RubyMine 3 0 我设置了 Rake 配置来运行单元测试 然后我设置了一些断点 然后运行 Rake 任务 没有命中断点 测试只是像平常一样执行 然后退出 RubyMine 调试器无法通过 Rake 运行吗 尝试这个 转到运行
  • 如何从 JavaScript 调用 ASSX?

    我想调用一个 ASHX 文件并从 JavaScript 传递一些查询字符串变量 并将返回字符串获取到 JavaScript 中的字符串中 我该怎么做 ASHX 文件已被编码为response write 一个基于查询字符串的字符串 像这样的
  • Rails:在任何源中都找不到并发 ruby​​-1.0.5 (Bundler::GemNotFound)

    我已经用谷歌搜索了很多 但没有发现任何对我的情况有用的东西 docker compose up abc 在日志中生成以下内容 usr lib ruby vendor ruby bundler spec set rb 92 in block
  • C 预处理器中的宏评估

    我想做这样的事情 define NUM ARGS 2 define MYMACRO0 no args define MYMACRO1 one arg define MYMACRO2 two args define MYMACRO num M
  • C++ 为伪随机数生成器生成良好的随机种子

    我正在尝试为伪随机数生成器生成一个好的随机种子 我想我应该得到专家的意见 让我知道这是否是一个不好的方法或者是否有更好的方法 include
  • 如何编写一个计算表达式生成器来累积值并允许标准语言构造?

    我有一个计算表达式生成器 可以随时生成值 并且有许多自定义操作 但是 它不允许标准 F 语言构造 并且我在弄清楚如何添加此支持方面遇到了很多麻烦 举一个独立的例子 下面是一个非常简单且毫无意义的构建 F 列表的计算表达式 type Item