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绑定值。我认为编译器目前所做的不是正确的行为。我看不出这两种情况有什么不同的表现。这就是为什么我说它看起来像一只虫子。