如何使F#编译器将我的参数推断给泛型函数?

Cth*_*utu 2 generics f#

我编写了一些测试代码来绕过泛型语法:

let add_stuff<'T> x y =
   printfn "%A" (x + y)

let stuff() = 
    add_stuff 5.5 2.4
    add_stuff 3 4
Run Code Online (Sandbox Code Playgroud)

第二次add_stuff调用无法编译。为什么是这样?为什么编译器不推断类型?

AMi*_*res 5

该代码有2个问题:

首先,'T任何参数都不使用泛型类型。参数需要声明为以下类型'T

// val add_stuff: 'T -> 'T -> unit
let add_stuff<'T> (x:'T) (y:'T) =
    printfn "%A" (x + y)
Run Code Online (Sandbox Code Playgroud)

这将创建一个新的错误消息:

在此不能使用声明的类型参数“ T”,因为在编译时无法解析类型参数

在这种情况下,问题在于+操作员。它使用静态解析的类型参数,这意味着您的函数也需要使用它们,这基本上意味着需要对其进行内联:

// val add_stuff: ^T -> ^T -> unit
let inline add_stuff (x:^T) (y:^T) =
    printfn "%A" (x + y)
Run Code Online (Sandbox Code Playgroud)

请注意,类型签名的区别'T是通用类型,可以在运行时解决。^T是SRTP,需要在编译时解析,因此需要inline关键字。

如果您没有使用过+运算符,则无需内联它。注意之间的区别pair_stuffadd_stuff

// val pair_stuff: 'T -> 'W -> unit
let pair_stuff (x:'T) (y:'W) =
    printfn "%A" (x , y)

// val add_stuff:  ^a -> ^b -> unit
let inline add_stuff x y =
    printfn "%A" (x + y)

let stuff() = 
    add_stuff 5.5 2.4
    add_stuff 3 4
    pair_stuff 5.5 2.4
    pair_stuff 3 4

stuff()
// 7.9
// 7
// (5.5, 2.4)
// (3, 4)
Run Code Online (Sandbox Code Playgroud)