Types 咖喱';灵活类型';在F#

Types 咖喱';灵活类型';在F#,types,f#,currying,Types,F#,Currying,代码的一小部分用来突出问题: open System.IO let do_smth i (stm : #System.IO.Stream) = // val do_smth : 'a -> #Stream -> unit (*....*) () type SomeOps = SomeOps with static member op (i : int) = do_smth i let test_currying i = do_smth i

代码的一小部分用来突出问题:

open System.IO

let do_smth i (stm : #System.IO.Stream) =  // val do_smth : 'a -> #Stream -> unit
    (*....*)
    ()

type SomeOps = SomeOps with
    static member op (i : int) = do_smth i

let test_currying i = do_smth i            // val test_currying : 'a -> (Stream -> unit)
                                           // NB: Stream, not #Stream
let main() = 
    use stm = new System.IO.MemoryStream()
    test_currying 42 stm  // OK, upcasted to Stream somehow
    SomeOps.op 42 stm     // compiler error!

有人能解释一下,为什么编译器的行为在最后两行中如此不同?为什么我们在
test\u currying
函数中丢失了有关flexible
#Stream
的信息呢?

对我来说,这看起来像个bug。编译器以不同的方式处理使用
let
构造的函数和作为
静态成员编写的函数

特别是,我认为它不会为未在成员声明中显式声明的成员参数(即,部分函数应用程序的结果或使用
fun
构造创建的参数)插入灵活类型

演示该行为的最简单示例不使用flexible type,如下所示:

type A = 
  static member op = fun (s:obj) -> ()
module B =
  let op = fun (s:obj) -> ()

A.op "A" // Error 
B.op "A" // Ok

根据规范(Brian在删除(?)答案中发布的部分),应该插入允许使用超类型的灵活类型,无论调用的函数是成员还是let绑定值。

我认为编译器目前所做的不是正确的行为。我看不出这两种情况有什么不同的表现。这就是为什么我说它看起来像一只虫子。