首页 文章

使用显式指定的泛型参数推断通用约束

提问于
浏览
0

考虑以下代码:

let f<'a when 'a:comparison> (x: 'a) = ()
let g x = f x
let h<'b> (x: 'b) = f x

函数 f 具有通过比较约束的通用参数 .
在函数 g 中,我只使用 f 并让编译器推断它正确执行的泛型参数,从而产生 g: 'a -> unit when 'a : comparison .

但是,如果我需要显式指定泛型参数,如函数 h ,编译器由于某种原因无法推断约束,导致 x 下的红色波浪形,说“类型参数缺少约束'when ' b:比较' . ”

这对于没有非泛型参数的函数尤其令人讨厌,即 let f<'a> = () ,或者其非泛型参数没有提及泛型类型,即 let f<'a> () = () ,因为我每次使用时都必须指定约束 . 函数在另一个泛型函数中:

let f<'a when 'a:comparison> () = ()
let g<'a> () = f<'a> () // Error: A type parameter is missing a constraint 
let h () = f<'a> () // h gets inferred as unit -> unit, losing generic parameter
let k<'a when 'a:comparison> () = f<'a> () // The only working way

是否有一个技巧让编译器为我推断约束?

2 回答

  • 2

    从第二组函数中删除 gh 生成警告:

    此构造使代码不如类型注释所指示的那样通用 . 类型变量'a已被约束为类型'System.IComparable' .

    所以,似乎 g 中的错误阻止了 h 的完整类型检查 .

  • 1

    只要您只在参数和/或返回类型之后注释类型参数,而不是函数名称,类型推断似乎有效 .

    从你的第一个例子开始:

    let f<'a when 'a:comparison> (x: 'a) = ()
    
    let i (x: 'b) = f x 
    // val i : x:'b -> unit when 'b : comparison
    

    如果参数本身具有泛型类型和/或其他类型约束,它也可以工作:

    let j (x: 'c list) = f x.Head
    // val j : x:'c list -> unit when 'c : comparison
    
    let k (x: 'd when 'd:unmanaged) = f x
    // val k : x:'d -> unit when 'd : unmanaged and 'd : comparison
    

    你应该能够以这种方式编写代码,因为在函数名中指定type参数是不必要的 .

    即使您不止一次使用约束类型,您也只需要在第一次描述它:

    let l (x: 'e when 'e:unmanaged) (y : 'e) = f x
    // val l : x:'e -> y:'e -> unit when 'e : unmanaged and 'e : comparison
    

    所有相同的技巧都适用于返回类型:

    let f'<'a when 'a:comparison> () = (new obj ()) :?> 'a
    
    let g' () : 'b when 'b : unmanaged = f' ()
    // val g' : unit -> 'b when 'b : unmanaged and 'b : comparison
    

    因此,唯一的痛点是泛型函数既没有通用输入参数也没有泛型返回类型 .

相关问题