我已经远远地看了解答案,但已经用尽所有的尝试。
我想覆盖已在项目中定义的自定义运算符,即经典的compose select t3.id,t3.ath_id,t3.brand_id,t3.time,t3.date
from times1 t3
inner join
(
select t1.ath_id,t1.brand_id,t1.date,t1.time,count(*) as rnk
from times1 t1
inner join times1 t2
on t1.ath_id=t2.ath_id
and t1.brand_id=t2.brand_id
and t1.date=t2.date
and t1.time >= t2.time
where t1.ath_id=4298584
group by t1.ath_id,t1.brand_id,t1.date,t1.time
) t4
on t3.ath_id=t4.ath_id
and t3.brand_id=t4.brand_id
and t3.date=t4.date
and t3.time = t4.time
and t4.rnk=1
;
运算符,这样如果它与我的类类型一起使用,它将使用其静态运算符重载,但每次使用时使用>=>
运算符的类,它给出了我的类与全局运算符定义不兼容的错误。帮助解释:
>=>
这样我可以编写可以包装像
这样的组合处理程序的代码type Handler = context -> context option // context just placeholder for type
let (>=>) (a:Handler) (b:Handler) = fun ctx -> match a ctx with | Some u -> b u | None
type Node(key) =
...
member static (>=>) (p:Node,h:Handler) = ...
member static (>=>) (p:Node,pl Node list) = ...
但不幸的是,类上的静态方法重载不能覆盖全局运算符并优先...有什么我可以做的事情来覆盖全局运算符来使其工作!? ...我知道我可以将我的Handle从类型扩充更改为完整类实现,删除全局运算符并仅对这两个类使用静态覆盖,但要与我正在查看的现有框架集成,需要是一个函数这种格式...
我在考虑过度加载FSharpFunc>使用静态成员(> =>)但在f#中,这需要在原始声明位置声明,这是不受限制的。
我在c#中声称要使用虚拟方法覆盖重载运算符,但这似乎不起作用。
所有这些Hacking(想要更好的词)是使用Node类来维护compose运算符格式,以存储这些处理程序以构建到Node树中。子列表是可选的这一事实意味着虽然我可以使用// val Node = Node (overloaded >=>) Handler (overloaded >=>) Handler (overloaded >=>) [ ... ]
let node = Node "key1" >=> handler1 >=> hander2 >=> [
Node "key2" >=> handler3
// val Handler = Handler (global >=>) Handler
let handler3 = handler1 >=> handler2
]
/ (key, composedHandlers)
的元组重载构造函数,但这将太丑陋并且被包裹以被接受,即:
(key, composedHandlers, ChildList)
我可以将类静态运算符更改为类似let node1 = Node ("key1", handle1 >=> handle2 , [
Node ("key2",handle3 >=> handle4, [
Node ("key3",handle5)
])
])
/ =>
的内容,但这会导致混淆何时使用==>
或使用>=>
,这太过分了要求用户弄清楚处理程序是否正在进入某个节点,或者他们是否纯粹将两个处理程序合并为一个。
如果静态解析的类型条件没有锁定到Core,我可以执行以下操作......但不允许:
=>
问题归结为:如何使操作符类型成为条件或如何使重载类操作符覆盖全局操作符,以便我可以根据中缀类型一起使用它们。
--- --- EDIT
@Gustavo链接的帖子正是我想要的:
let (>=>) (a:^T) (b:Handler)
when ^T : Handler = ...
when ^T : Node = ...
when ^T : Node list = ...
答案 0 :(得分:3)
我对this question的回答显示了如何重新连接全局运营商。
如果你发布了一个最小的repro,我可以告诉你如何将它应用到你的案例中。
话虽如此,我建议您使用已包含>=>
运算符Bind
的{{3}},并且要使其与您的类一起工作所需要做的就是定义Return
和static member Return a = ...
static member Bind (x, f) = ...
,如下所示:
parameters.yml
同样,如果您向我展示您的代码,我可以提供更多详细信息。
答案 1 :(得分:0)
我认为没有办法完全 你想要什么,但如果你的目标是生产一个漂亮的DSL,你可以采用一个稍微不同的路线:将“只是节点”的情况和“带有处理程序的节点应用”的情况转换为DU,然后在那个DU上定义运算符:
type Handler = context -> context option
type Node = Node of key:string
type Composable = CNode of Node | CHandled of Handler
let node key = CNode (Node key)
let inline (>=>) (a:Composable) (b:Handler) =
match a with
| CNode n -> ...
| CHandled h -> ...
// Usage:
let handler1 = fun ctx -> ...
let handler2 = fun ctx -> ...
let a = node "abc" >=> handler1 >=> handler2
这在语法上与原始签名相符,但我必须说它对我来说看起来有点荒谬,这是因为我不太明白你的最终目标是什么:Node
是什么?为什么需要“处理”?处理的结果是什么?从你的代码看来,“处理”的结果是另一个“处理程序”,但这是正确的吗?等等。
如果您能更好地澄清您的域名,我相信我们可以提出更好的解决方案。