title: F#: Overriding global operator with static method overload or type conditional operator
body: <p>I have looked far and wide for an answer to this but have exhausted all attempts.</p>
  
  <p>I want to override a custom operator already defined in a project, the classic compose <code>&gt;=&gt;</code> operator, such that if it is used with my class type, it will use its static operator overload instead but every time I use the class with the <code>&gt;=&gt;</code> operator, it gives me error that my class is not compatible with global operator definition. to help explain:</p>
  
  <pre><code>type Handler = context -&gt; context option // context just placeholder for type
  
  let (&gt;=&gt;) (a:Handler) (b:Handler) = fun ctx -&gt; match a ctx with | Some u -&gt; b u | None
  
  type Node(key) =
  ...
  member static (&gt;=&gt;) (p:Node,h:Handler) = ...
  member static (&gt;=&gt;) (p:Node,pl Node list) = ...
  </code></pre>
  
  <p>This is so that I may write code that can wrap the composed handlers like</p>
  
  <pre><code>// val Node = Node (overloaded &gt;=&gt;) Handler (overloaded &gt;=&gt;) Handler (overloaded &gt;=&gt;) [ ... ]
  let node = Node "key1" &gt;=&gt; handler1 &gt;=&gt; hander2 &gt;=&gt; [
                                  Node "key2" &gt;=&gt; handler3
  // val Handler = Handler (global &gt;=&gt;) Handler
  let handler3 = handler1 &gt;=&gt; handler2 
                                  ]
  </code></pre>
  
  <p>But unfortunately, the static method overloads on the class cannot override the global operator and take precedence ... is there anything I can do to override the global operator to make this work!? ... I know I can change my Handle from a type augmentation to a full class implementation, remove global operator and use only static overrides on the two classes but to integrate with the existing framework i'm looking at, needs to be a function of this format ... </p>
  
  <p>I was thinking of perhaps overloading FSharpFunc> with static member (>=>) but in f# this would need to be declared in the original declaration location which is off limits.</p>
  
  <p>I looked into claimed way in c# to override with overload operator using virtual methods but this didn't seem to work.</p>
  
  <p>All this Hacking (for want of a better word) is to maintain the compose operator format while using a Node class to store these handlers to build into a Node tree. The fact that the child lists are optional means that although I could overload the constructor using tuples of <code>(key, composedHandlers)</code> / <code>(key, composedHandlers, ChildList)</code>, this would be too ugly and wrapped to be accepted ie:</p>
  
  <pre><code>let node1 = Node ("key1", handle1 &gt;=&gt; handle2 , [
                                          Node ("key2",handle3 &gt;=&gt; handle4, [
                                                                      Node ("key3",handle5)
                                                                      ])
                                                  ])
  </code></pre>
  
  <p>I could change the class static operator to something like <code>=&gt;</code> / <code>==&gt;</code> but then it causes confusion as to when to use <code>&gt;=&gt;</code> or use <code>=&gt;</code>, it's too much to ask a user to figure out if handlers are feeding into a node or are they purely composing two handlers into one.</p>
  
  <p>If statically resolved type conditions were not locked to only Core I could do something like the following ... but not allowed:</p>
  
  <pre><code>let (&gt;=&gt;) (a:^T) (b:Handler)
       when ^T : Handler   = ...
       when ^T : Node      = ...
       when ^T : Node list = ...
  </code></pre>
  
  <p>The issue boils down to, How can I make operator type conditional or how can I make an overloaded class operator override a global operator so that I can use both together depending on the infix types.</p>
  
  <p>---EDIT---</p>
  
  <p>@Gustavo linked post was exactly what I was looking for:</p>
  
  <pre><code>type ComposeExtension = ComposeExtension with
      static member        (?&lt;-) (ComposeExtension, (a:PathNode) , (b:HttpHandler)) = a.AddHandler b
      static member        (?&lt;-) (ComposeExtension, (a:PathNode) , (b:PathNode list)) = a.AddChildPaths b
      static member inline (?&lt;-) (ComposeExtension, a , b) = a &gt;=&gt; b
  let inline (&gt;=&gt;) a b = (?&lt;-) ComposeExtension a b
  </code></pre>