Types 为什么可以';不能为嵌套函数推断类型

Types 为什么可以';不能为嵌套函数推断类型,types,f#,type-inference,Types,F#,Type Inference,我不了解嵌套函数的F#类型推理系统。当我在简单类型(如int、string、…)之外使用类型时,它似乎特别脆弱 下面是一些代码打印一些反射信息的小示例 let inferenceTest () = let t = int.GetType() let methods = t.GetMethods() |> Seq.map(fun m -> m.Name) printfn "%s" <| String.concat ", " methods 基本上类型推断

我不了解嵌套函数的F#类型推理系统。当我在简单类型(如int、string、…)之外使用类型时,它似乎特别脆弱

下面是一些代码打印一些反射信息的小示例

let inferenceTest () =
    let t = int.GetType()
    let methods = t.GetMethods() |> Seq.map(fun m -> m.Name)
    printfn "%s" <| String.concat ", " methods

基本上类型推断是从上到下从左到右进行的。有很多例外情况,但我不想详细说明

在第一个示例中,推断引擎有足够的信息来正确推断类型

let inferenceTest () =
    let t = int.GetType()
    let methods = t.GetMethods() |> Seq.map(fun m -> m.Name)
    printfn "%s" <| String.concat ", " methods
在第二个示例中,这条线推断为

let printType (t : 'a) () = 
这导致了上的错误

let methods = t.GetMethods() |> Seq.map(fun m -> m.Name)
因为
t
的类型是泛型的,并且没有提供足够的信息用于
t.GetMethods()

为了解决这些问题,我使用VisualStudio并将鼠标移动到变量上以查看类型。然后,如果我发现一个类型不正确,我就开始添加类型定义。这通常会导致修复错误或发现代码中的错误

编辑:

这是by回答的一部分

F#使用一次编译,因此只能引用类型或 在您要创建的文件中先前定义的函数 当前位于或显示在中前面指定的文件中 汇编顺序

我最近向Don Syme询问了如何将多个源代码传递给 改进类型推断过程。他的回答是

“是的,可以进行多通道类型推断。还有 生成有限约束集的单过程变化

然而,这些方法往往会给出错误消息和错误信息 intellisense将生成一个可视化编辑器。”


请参阅:,作为旁注:
printType
不需要额外的
单元
参数。它有一个“real”参数,这足以将其限定为函数。感谢类型分解。我假设唯一可以调用我的函数
printType()
的是它定义的范围内的代码。因此,我不明白它不能推断唯一的用法是
MethodInfo[]
let t=int.GetType()
printType t
let methods=t.GetMethods()|>Seq.map(fun m->m.Name)
之后,所以推断引擎在到达
t.GetMethods
时不知道它们。有很多关于的论文,如果有人谈论您所寻求的,我不会感到惊讶,但是F#选择的实现是出于特定的原因。@CarloV.Dango如果是嵌套函数或谁可以调用它,则与此无关。F#尽量使用泛型,
printType
是一个只需要一个参数
t
的函数。您唯一要做的就是对它调用一个方法,并且您不能仅仅通过方法调用来安全地推断类型。因为每个类都可以实现该方法。因此,您会得到一个错误,此时无法确定类型。这是一个常规限制,如果将
getType
提取到其自身的函数非嵌套函数中,也会发生这种情况。@SidBurn类型系统会根据使用情况推断类型。因此,查看内部函数,查看它们的调用位置,并根据作为参数传递给它们的内容推断类型是非常有意义的。正如内部函数的代码在第一个函数中一样,在第二个函数中也是如此example@CarloV.Dango类型系统不会根据其用法推断对象类型,因为这里不可能推断任何内容。因为我已经解释过,你不能基于方法调用推断一个类,因为有这样一个方法可以存在数百万个类。无法推断对象的类型。唯一接近的是(静态)类型化的duck类型。因此,实现被调用方法的每个类都将被接受。但是F#不要自动地做这样的事情。
let inferenceTest () =
    let (t : type) = int.GetType()
    let methods = t.GetMethods() |> Seq.map(fun m -> m.Name)
    printfn "%s" <| String.concat ", " methods
let inferenceTest () =
    let (t : type) = int.GetType()
    let methods = (t.GetMethods() : System.Reflection.MethodInfo []) |> Seq.map(fun m -> m.Name)
    printfn "%s" <| String.concat ", " methods
let inferenceTest () =
    let (t : type) = int.GetType()
    let (methods : seq<string>) = (t.GetMethods() : System.Reflection.MethodInfo []) |> Seq.map(fun m -> m.Name)
    printfn "%s" <| String.concat ", " methods
let methods = Seq.map (fun m -> m.Name) (t.GetMethods())
let printType (t : 'a) () = 
let methods = t.GetMethods() |> Seq.map(fun m -> m.Name)