Ожидание типа, поддерживающего оператор» -«, но с учетом типа функции

#f#

#f#

Вопрос:

Может ли кто-нибудь пояснить, почему я получил это сообщение (см. Комментарий в двух строках ниже), и, возможно, указать на правильную спецификацию определяемых пользователем двоичных операторов. Почему я должен определять оператор (.—gt;.) вне определения типа и и не (.gt;gt;gt;gt;gt;=.)?

 type ListAlt;'Tgt; = NIL | Cons of 'T * ListAlt;'Tgt; with  static member cat (a:ListAlt;'Tgt;) (b:ListAlt;'Tgt;) :ListAlt;'Tgt;=  match a with  | NIL -gt; b  | Cons (a, tail) -gt; Cons (a, (ListAlt;'Tgt;.cat tail b))  static member join (a:ListAlt;ListAlt;'Tgt;gt;) =  match a with  | NIL -gt; NIL  | Cons (a, b) -gt; ListAlt;'Tgt;.cat a (ListAlt;'Tgt;.join b)   static member fmap (fn: 'T -gt; 'U) (a:ListAlt;'Tgt;) =  match a with  | NIL -gt; NIL  | Cons (a, tail) -gt; Cons ((fn a), (ListAlt;'Tgt;.fmap fn tail))    static member inline (.gt;gt;=.)(ma:ListAlt;'Tgt; , k:'T -gt; ListAlt;'Ugt;) = ListAlt;'Tgt;.fmap k ma |gt; ListAlt;_gt;.join   static member inline (.lt;lt;lt;.)(mbc:'B -gt; ListAlt;'Cgt; , mab:'T -gt; ListAlt;'Bgt;) = (fun x -gt; (mab x) .gt;gt;=. mbc)  static member inline (.gt;gt;gt;.)(mab:'T -gt; ListAlt;'Bgt; , mbc:'B -gt; ListAlt;'Cgt;) = (fun x -gt; (mab x) .gt;gt;=. mbc)    static member join2 (a:ListAlt;_gt;) = a .gt;gt;=. id      let (.--gt;.)(mab:'T -gt; ListAlt;'Bgt;) (mbc:'B -gt; ListAlt;'Cgt;) = (fun x -gt; (mab x) .gt;gt;=. mbc)  let (.lt;--.)(mab:'B -gt; ListAlt;'Cgt;) (mbc:'T -gt; ListAlt;'Bgt;) = (fun x -gt; (mbc x) .gt;gt;=. mab)    let f = fun x -gt; Cons (x, Cons ((x   1), NIL))   let g = fun x -gt; Cons (x * 2, NIL)  // NOT Compiling: let fgA = fun x -gt; (f .lt;lt;lt;. g)   // NOT Compiling: let fgB = fun x -gt; (f .gt;gt;gt;. g)   let fg = fun x -gt; (f x) .gt;gt;=. g  let fg1 = (f .--gt;. g .--gt;. g)  let fg2 = (f .lt;--. g .--gt;. f)  printfn "%A" (fg1 3)  

Ответ №1:

Таковы правила поиска операторов. Сначала (1) компилятор пытается определить, определен ли оператор как метод для одного из типов операндов, а затем (2) он пытается просмотреть текущий лексический контекст (т. е. текущий модуль и любые open модули ed).

(кстати, правило (1) является общим для всех .NET, в то время как правило (2) относится только к F#)

.gt;gt;=. работает, потому что он определен по типу своего первого аргумента (f x) , поэтому применяется правило (1).

.--gt;. работает, потому что это определено в текущем контексте, поэтому применяется правило (2).

Но в выражении f .gt;gt;gt;. g тип обоих аргументов является функцией 'a -gt; ListAlt;'agt; , и в этом типе оператор не .gt;gt;gt;. определен как метод, и .gt;gt;gt;. в текущем контексте оператор не определен, поэтому ни правило (1), ни правило (2) не применяются, и компилятор понятия не имеет, где искать этот оператор.

Комментарии:

1. Отличный ответ. Очень полезно

2. Если мой ответ помог вам, пожалуйста, подумайте о том, чтобы «принять» его. Вы можете сделать это, щелкнув бледно-серую галочку слева-это ответ.