代码之家  ›  专栏  ›  技术社区  ›  Gerard

F#:使用静态方法重载或类型条件运算符重写全局运算符

  •  2
  • Gerard  · 技术社区  · 8 年前

    >=> 运算符,因此,如果它与我的类类型一起使用,它将使用其静态运算符重载,但每次我使用带有 >=> 运算符,这给了我一个错误,我的类与全局运算符定义不兼容。帮助解释:

    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) = ...
    

    这样我就可以编写代码来包装组合的处理程序,如

    // 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 
                                    ]
    

    我在考虑是否重载FSharpFunc>具有静态成员(>=>)但在f#中,这需要在禁止进入的原始申报位置申报。

    我研究了c#中使用虚拟方法用重载运算符重写的方法,但这似乎不起作用。

    (key, composedHandlers) (key, composedHandlers, ChildList) ,这太难看了,包装得不可接受,即:

    let node1 = Node ("key1", handle1 >=> handle2 , [
                                            Node ("key2",handle3 >=> handle4, [
                                                                        Node ("key3",handle5)
                                                                        ])
                                                    ])
    

    我可以将类静态运算符改为 => / ==> >=> 或使用 ,要求用户确定处理程序是馈送到节点中,还是纯粹将两个处理程序组合成一个处理程序,这太过分了。

    let (>=>) (a:^T) (b:Handler)
         when ^T : Handler   = ...
         when ^T : Node      = ...
         when ^T : Node list = ...
    

    问题归结为,如何使运算符类型有条件,或者如何使重载类运算符重写全局运算符,以便根据中缀类型将两者结合使用。

    ---编辑---

    type ComposeExtension = ComposeExtension with
        static member        (?<-) (ComposeExtension, (a:PathNode) , (b:HttpHandler)) = a.AddHandler b
        static member        (?<-) (ComposeExtension, (a:PathNode) , (b:PathNode list)) = a.AddChildPaths b
        static member inline (?<-) (ComposeExtension, a , b) = a >=> b
    let inline (>=>) a b = (?<-) ComposeExtension a b
    
    2 回复  |  直到 4 年前
        1
  •  3
  •   Gus    8 年前

    我的答案 this question 演示如何重新连接全局运算符。

    如果你发布一个最小的复制,我可以告诉你如何将其应用到你的案例中。

    FSharpPlus better global definition 操作员的 >=> 为了让它在你的课堂上发挥作用,你所要做的就是定义 Bind Return ,如下所示:

    static member Return a = ...
    static member Bind  (x, f) = ...
    

        2
  •  0
  •   Fyodor Soikin    8 年前

    我认为没有办法 确切地

    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

    如果你能更好地澄清你的领域,我相信我们能想出更好的解决方案。