【问题标题】:Expecting a type supporting the operator '-' but given a function type期望一个支持运算符“-”但给定函数类型的类型
【发布时间】:2022-01-07 03:13:06
【问题描述】:

谁能澄清我收到此消息的原因(请参阅下面注释的两行),并可能指出用户定义的二元运算符的正确规范。 为什么我必须在类型定义之外定义运算符 (.-->.) 而不是 (.>>=.)?

type ListA<'T> = NIL | Cons of 'T * ListA<'T> with
        static member cat (a:ListA<'T>) (b:ListA<'T>) :ListA<'T>=
            match a with
                | NIL -> b
                | Cons (a, tail) -> Cons (a, (ListA<'T>.cat tail b))
        static member join (a:ListA<ListA<'T>>)  =
            match a with
                | NIL -> NIL
                | Cons (a, b) -> ListA<'T>.cat a (ListA<'T>.join b)

        static member fmap (fn: 'T -> 'U) (a:ListA<'T>)  =
                 match a with
                    | NIL -> NIL
                    | Cons (a, tail) -> Cons ((fn a), (ListA<'T>.fmap fn tail))
        
        static member inline (.>>=.)(ma:ListA<'T> , k:'T -> ListA<'U>) =  ListA<'T>.fmap k ma |> ListA<_>.join

        static member inline (.<<<.)(mbc:'B -> ListA<'C> , mab:'T -> ListA<'B>) = (fun x -> (mab x) .>>=. mbc)
        static member inline (.>>>.)(mab:'T -> ListA<'B> , mbc:'B -> ListA<'C>) = (fun x -> (mab x) .>>=. mbc)
        
        static member join2 (a:ListA<_>)  =  a .>>=. id
    
    
    let (.-->.)(mab:'T -> ListA<'B>) (mbc:'B -> ListA<'C>) = (fun x -> (mab x) .>>=. mbc)
    let (.<--.)(mab:'B -> ListA<'C>) (mbc:'T -> ListA<'B>) = (fun x -> (mbc x) .>>=. mab)
    
    let f  = fun x ->  Cons (x, Cons ((x + 1), NIL))    
    let g  = fun x ->  Cons (x * 2, NIL)
    // NOT Compiling: let fgA = fun x -> (f .<<<. g) 
    // NOT Compiling: let fgB = fun x -> (f .>>>. g) 
    let fg = fun x -> (f x) .>>=. g
    let fg1 = (f .-->. g .-->. g)
    let fg2 = (f .<--. g .-->. f)
    printfn "%A" (fg1 3)

【问题讨论】:

    标签: f#


    【解决方案1】:

    这就是运算符查找的规则。首先 (1) 编译器尝试查看操作符是否定义为操作数类型之一的方法,然后 (2) 它尝试查看当前的词法上下文(即当前模块和任何 opened模块)。

    (顺便说一下,规则 (1) 对所有 .NET 都是通用的,而规则 (2) 仅适用于 F#)

    .&gt;&gt;=. 有效,因为它是在其第一个参数 (f x) 的类型上定义的,因此适用规则 (1)。

    .--&gt;. 有效,因为它是在当前上下文中定义的,因此适用规则 (2)。

    但是在表达式f .&gt;&gt;&gt;. g中,两个参数的类型都是函数'a -&gt; ListA&lt;'a&gt;,并且这个类型没有定义操作符.&gt;&gt;&gt;.作为方法,并且当前上下文没有定义操作符.&gt;&gt;&gt;. ,因此规则 (1) 和规则 (2) 都不适用,编译器不知道在哪里查找此运算符。

    【讨论】:

    • 优秀的答案。很有帮助
    • 如果我的回答对你有帮助,请考虑“接受”。您可以通过单击左侧的浅灰色复选标记来做到这一点就是答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多