Generics f#curry函数丢失泛型类型?

Generics f#curry函数丢失泛型类型?,generics,f#,type-inference,Generics,F#,Type Inference,当我尝试将最后一个参数作为泛型类型来curry函数时,编译器会强制将泛型类型转换为它找到的第一个具体类型,从而在范围内的后续调用中丢失其泛型属性。例如: type Bar = | String | Integer | Boolean let foo (a: String)(b: 'm) = printfn "%A - %A" a b let foobar (a: String)(bar: Bar) = let fooWithA= foo a m

当我尝试将最后一个参数作为泛型类型来curry函数时,编译器会强制将泛型类型转换为它找到的第一个具体类型,从而在范围内的后续调用中丢失其泛型属性。例如:

type Bar =
    | String
    | Integer
    | Boolean

let foo (a: String)(b: 'm) =
    printfn "%A - %A" a b

let foobar (a: String)(bar: Bar) =
    let fooWithA= foo a
    match bar with
    | String -> fooWithA "String"
    | Integer -> fooWithA 42
    | Boolean -> fooWithA true
这里的最后两行给出了一个编译器错误,说明函数需要一个字符串。但是,如果我用一个helper类包装函数,我可以使它像这样工作:

type FooHelper(a:String) =
    member this.foo (b: 'm) =
        printfn "%A - %A" a b

let foobar (a: String)(bar: Bar) =
    let fooHelperWithA= FooHelper a
    match bar with
    | String -> fooHelperWithA.foo "String"
    | Integer -> fooHelperWithA.foo 42
    | Boolean -> fooHelperWithA.foo true
这不会给我一个编译器错误。然后,如果我尝试直接使用该函数,则再次出现编译错误:

let foobar (a: String)(bar: Bar) =
    let fooHelperWithA= FooHelper(a).foo
    match bar with
    | String -> fooHelperWithA "String"
    | Integer -> fooHelperWithA 42
    | Boolean -> fooHelperWithA true
最后两行抛出编译错误


这是一个预期的行为还是一个bug?如果是这样的话,有人能解释一下原因吗?这让我很困惑。

所以这是一个典型的值限制问题。如果只执行以下代码块,则更为明显:

let foo (a: String)(b: 'm) =
    printfn "%A - %A" a b 
let fooWithA= foo  "hello"
这将导致以下错误:

错误FS0030:值限制。已推断值“fooWithA”具有泛型类型 val fooWithA:(''单位->单位)
使“fooWithA”的参数显式,或者,如果不希望它是泛型的,则添加类型注释

问题在于
fooWithA
不是一个正确的函数,因此,它不允许具有泛型类型

因此在第一个示例中,编译器看到您首先使用字符串调用它,因此它进行了专门化,然后对整数和布尔情况失败

在第二个示例中,您隐式创建了一个函数,该函数可以被设置为泛型函数,因此一切都很好

在第三个示例中,您遇到了与第一个示例相同的问题,您将函数绑定到一个值,因此它不能是泛型的

解决所有这些问题的最简单方法是始终使用这样的函数

let fooWithA a = foo "hello" a

这是一个经典的值限制问题。如果只执行以下代码块,则更为明显:

let foo (a: String)(b: 'm) =
    printfn "%A - %A" a b 
let fooWithA= foo  "hello"
这将导致以下错误:

错误FS0030:值限制。已推断值“fooWithA”具有泛型类型 val fooWithA:(''单位->单位)
使“fooWithA”的参数显式,或者,如果不希望它是泛型的,则添加类型注释

问题在于
fooWithA
不是一个正确的函数,因此,它不允许具有泛型类型

因此在第一个示例中,编译器看到您首先使用字符串调用它,因此它进行了专门化,然后对整数和布尔情况失败

在第二个示例中,您隐式创建了一个函数,该函数可以被设置为泛型函数,因此一切都很好

在第三个示例中,您遇到了与第一个示例相同的问题,您将函数绑定到一个值,因此它不能是泛型的

解决所有这些问题的最简单方法是始终使用这样的函数

let fooWithA a = foo "hello" a
有关更多副本,请参阅有关更多副本,请参阅我看到。。。我对F#有点陌生,当听说curry时,我认为它们与一些参数设置为默认值的函数完全一样。我想我错了。你的简单解决方案对我来说很有用:)我明白了。。。我对F#有点陌生,当听说curry时,我认为它们与一些参数设置为默认值的函数完全一样。我想我错了。您的简单解决方案为我带来了好处:)