解决类似泛型类型的运算符冲突

时间:2015-08-13 18:01:12

标签: f#

我使用第三方库(Sauve.IO)来定义标准绑定运算符>> =:

 val inline (>>=) : first:('T -> Async<'U option>) -> second:('U -> Async<'V option>) -> input:'T -> Async<'V option>

我还有一个内部库,它也希望通过类型签名

定义运算符
Async<Response<'a>> -> ('a -> Async<Response<'b>>) -> Async<Response<'b>>

在不影响重载内联函数的限制的情况下,在同一命名空间/模块中使用这两个函数的最简洁方法是什么?

3 个答案:

答案 0 :(得分:3)

如何将Suave的运算符重命名为其他中缀运算符?

let (>=>) = Suave.(>>=)

从签名来看,无论如何它看起来都没有绑定, 但实际上是Kleisli composition

答案 1 :(得分:2)

您可以利用F#的静态解析ad-hoc多态性:将合格的运算符调用隐藏在单独的重载运算符后面;然后定义另一个内联运算符以供实际使用。

type Foo = Foo with
    static member ($) (_ : Foo, first : _ -> Async<_ option>) =
        fun second value -> Module1.(>>=) first second value 
    static member ($) (_ : Foo, arg1 : Async<Response<_>>) =
        Module2.(>>=) arg1

let inline (>>=) arg1 arg2 = (Foo $ arg1) arg2

答案 2 :(得分:0)

两个运营商是否都具有相同的名称(>>=)? 如果是这样,我认为Suave的运营商带有它自己的模块或命名空间? 在这种情况下,您可以限定其运算符附加其模块/命名空间名称,如Suave.(>>=),但在这种情况下,您必须将其称为通常的函数。这是一个简化的例子:

module Suave =
    let inline (>>=) a b = a + 2 * b 


module Mine = 
    open Suave
    let (>>=) a b = a - 3 * b 

    let r1 = Suave.(>>=) 1 3 
    let r2 = 1 >>= 3 

结果:

  val r1 : int = 7
  val r2 : int = -8