突出问题的代码的一小部分:
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!
有人可以解释,为什么编译器的行为在最后两行中如此不同?为什么我们在#Stream
函数中丢失了信息(关于灵活的test_currying
)?
答案 0 :(得分:3)
对我来说这看起来像个错误。编译器处理使用let
构造的不同函数和编写为static member
的函数。
特别是,我认为它不会为未在成员声明中显式声明的成员参数插入灵活类型(即,部分函数应用的结果或使用{{1}创建的参数}构造)。
演示行为的最简单示例不使用灵活类型,如下所示:
fun
根据规范(部分14.4.2,由Brian在删除的(?)答案中发布),无论被调用的函数是成员还是let-bound,都应该插入允许使用超类型的灵活类型值。