我可以在F#中重新编程op_Equals吗?

时间:2016-04-15 17:13:30

标签: f# equals operator-keyword dsl

我在F#做了一个有趣的项目,这是DSL for Camel.Net

在某些时候,我想查看条件。但程序员输入的条件应该评估为对象树。所以我想要表达" a = b"评估为" SomeType.Equals(a,b)"

在F#中甚至可以吗?

我有这个:

type Macro = 
|   Header of string
|   XPath  of string
|   Const  of string
|   Func   of (Message -> string)
with
    static member (=) (l:Macro, r:Macro) = Equals(l,r)
    static member (=) (l:Macro, r:string) = Equals(l,Const(r))
and Comparison =
|   Equals of Macro * Macro

现在所有内容都在" Macro"将作为" Macro.Func" - 用" Func&#34 ;;使用" Message"执行函数。作为输入参数并将输出字符串。因此,Equals(a,b)将在运行时评估为字符串比较。

但是这段代码有问题。运算符(=)确实编译(它有一个警告),但它不能按我的意愿使用。

这不能在fsi:

中编译
let c1 = Header("property") = "somevalue"

我确实阅读了关于此主题的another questionbit more

它没有回答我的问题。

[<NoEquality; NoComparison>] - 完全关闭(=)运算符。

[<CustomEquality; CustomComparison>] - 希望你实现一个返回bool的(=)运算符。

甚至可以在F#中找到我想要的东西吗?假设我能找到方法,match x with是否仍然有效?

2 个答案:

答案 0 :(得分:2)

当然,出于性能原因,我在System.IEquatable<T>方面对运营商进行了重新实施:

#nowarn "86" // F# doesn't like it when you do this

[<AutoOpen>]
module FastEquals =
    let inline eq<'a when 'a :> System.IEquatable<'a>> (x:'a) (y:'a) = x.Equals y    
    let inline (=) x y = eq x y
    let inline (<>) x y = not (eq x y)

举个例子,你需要适应自己的目的。

答案 1 :(得分:2)

感谢上述Asik的回答,结合重读this post

这适用于fsi:

KeyError: 'ecoinvent 3_2 CutOff'

请注意,当静态“CompareEquals”方法位于“宏”类型中时,它不起作用。

如果你看一下op_Equals的签名:

type Message = class end

type Macro = 
|   Header of string
|   XPath  of string
|   Const  of string
|   Func   of (Message -> string)

type Comparison =
|   Equals of Macro * Macro

type Operators = Operation with
    static member CompareEquals (Operation, l:Macro, r:Macro) = Equals(l,r)
    static member CompareEquals (Operation, l:Macro, r:string) = Equals(l,Const(r))

#nowarn "0086" "0064"
let inline (=) (l:'N) (r:'M) = ((^T or ^N or ^M) : (static member CompareEquals : ^T * ^N * ^M -> _) (Operation, l, r))

let c1 = Header("property1") = Header("property2")
let c2 = Header("property") = "somevalue"

这是一个非常奇怪的语法。我不明白“什么时候”之后的部分。这很有效,重要。