升级 FParsec:升级可区分联合以满足新的相等/比较约束

发布于 2024-08-21 15:55:49 字数 1482 浏览 9 评论 0原文

因此,通过 嗨<在发生了一系列事件之后,我下载了 FParsec 源代码并尝试构建它。不幸的是,它与新的 1.9.9.9 不兼容。我解决了简单的问题,但有几个受歧视的工会仍然不起作用。

具体来说, Don Syme 的文章 解释了包含 obj-> 类型项的可区分联合不会自动获得相等或比较约束,因为对象不支持比较,函数也不支持相等。 (目前尚不清楚自动生成的相等/比较之前是否有错误,但现在不再生成代码,代码甚至无法编译。)

以下是有问题的 DU 的一些示例:

type PrecedenceParserOp<'a,'u'> =
     | PrefixOp of string * Parser<unit,'u> * int * bool * ('a -> 'a)
     | others ...

type ErrorMessage =
     | ...
     | OtherError of obj
     | ...

以下是违规用途:

member t.RemoveOperator (op: PrecedenceParserOp<'a, 'u>) =
    // some code ...
    if top.OriginalOp <> op then false // requires equality constraint
    // etc etc ...

或者,对于比较约束

let rec printMessages (pos: Pos) (msgs: ErrorMessage list) ind =
    // other code ...
    for msg in Set.ofList msgs do // iterate over ordered unique messages
        // etc etc ...

据我所知,Don 的解决方案是用唯一的 int 标记每个实例,这是实现自定义相等/比较约束的正确方法(或者可能是唯一的 int 元组,以便可以对 DU 的各个分支进行排序) )。但这对于DU的用户来说是不方便的。现在,DU 的构建需要调用函数来获取下一个标记。

是否有某种方法可以隐藏标签获取并向库的用户提供相同的构造函数?即改变实现而不改变接口?这一点尤其重要,因为(根据我对代码的理解)PrecedenceParserOp 似乎是一个公共类型。

So, by a hilarious series of events, I downloaded the FParsec source and tried to build it. Unfortunately, it's not compatible with the new 1.9.9.9. I fixed the easy problems, but there are a couple of discriminated unions that still don't work.

Specifically, Don Syme's post explains that discriminated unions containing items of type obj or -> don't automatically get equality or comparison constraints, since objects don't support comparison and functions don't support equality either. (It's not clear whether the automatically generated equality/comparison was buggy before, but the code won't even compile now that they're no longer generated.)

Here are some examples of the problematic DUs:

type PrecedenceParserOp<'a,'u'> =
     | PrefixOp of string * Parser<unit,'u> * int * bool * ('a -> 'a)
     | others ...

type ErrorMessage =
     | ...
     | OtherError of obj
     | ...

Here are the offending uses:

member t.RemoveOperator (op: PrecedenceParserOp<'a, 'u>) =
    // some code ...
    if top.OriginalOp <> op then false // requires equality constraint
    // etc etc ...

or, for the comparison constraint

let rec printMessages (pos: Pos) (msgs: ErrorMessage list) ind =
    // other code ...
    for msg in Set.ofList msgs do // iterate over ordered unique messages
        // etc etc ...

As far I can tell, Don's solution of tagging each instance with a unique int is the Right Way to implement a custom equality/comparison constraint (or a maybe a unique int tuple so that individual branches of the DU can be ordered). But this is inconvenient for the user of the DU. Now, construction of the DU requires calling a function to get the next stamp.

Is there some way to hide the tag-getting and present the same constructors to users of the library? That is, to change the implementation without changing the interface? This is especially important because it appears (from what I understand of the code) that PrecedenceParserOp is a public type.

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

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

发布评论

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

评论(2

嘿看小鸭子会跑 2024-08-28 15:55:49

您下载的 FParsec 来源是什么?我从 FParsec BitBucket 存储库 获取了最新版本,并且无需在全部转到 FParsec 源代码以使其在 VS 2010 RC 中进行编译。

编辑:我收回那句话。我确实从 InterpLexYacc 和 InterpFParsec 示例项目中遇到了构建错误,但核心 FParsec 和 FParsecCS 项目构建得很好。

What source did you download for FParsec? I grabbed the latest from the FParsec BitBucket repository, and I didn't have to make any changes at all to the FParsec source to get it to compile in VS 2010 RC.

Edit: I take that back. I did get build errors from the InterpLexYacc and InterpFParsec sample projects, but the core FParsec and FParsecCS projects build just fine.

我为君王 2024-08-28 15:55:49

您可以做的一件事是添加 [][] 属性并定义您自己的 .Equals 覆盖和IComparable 实现。当然,这需要您处理 obj_ ->; _ 以适当的方式自行组件,这可能可行,也可能不可能。如果您可以控制传递到 OtherError 构造函数中的内容,则应该能够通过向下转换 obj 来使该操作适用于 ErrorMessage 类型其本身在结构上具有可比性。但是,PrecendenceParserOp 情况有点棘手 - 只要您不需要比较,您就可以在函数组件上使用引用相等。

One thing you could do is add [<CustomEquality>] and [<CustomComparison>] attributes and define your own .Equals override and IComparable implementation. Of course, this would require you to handle the obj and _ -> _ components yourself in an appropriate way, which may or may not be possible. If you can control what's being passed into the OtherError constructor, you ought to be able to make this work for the ErrorMessage type by downcasting the obj to a type which is itself structurally comparable. However, the PrecendenceParserOp case is a bit trickier - you might be able to get by with using reference equality on the function components as long as you don't need comparison as well.

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