Mat*_*ath 6 generics f# type-inference
我已经定义了以下类型(从代码中简化):
type Polynomial<'a when 'a :(static member public Zero : 'a) 
                and 'a: (static member (+): 'a*'a -> 'a) 
                and 'a : (static member (*): 'a*'a -> 'a) >  =
    | Polynomial of 'a list
    with 
    static member inline (+) (x: Polynomial<'a> , y : Polynomial<'a>) : Polynomial<'a>= 
        match x,y with
        |Polynomial xlist, Polynomial ylist ->
            let longer, shorter = 
                if xlist.Length> ylist.Length then xlist, ylist
                else ylist, xlist
            let shorterExtended = List.append shorter (List.init (longer.Length - shorter.Length) (fun _ -> LanguagePrimitives.GenericZero<'a>))
            List.map2 (+) longer shorterExtended |> Polynomial
Run Code Online (Sandbox Code Playgroud)
当我建立时,我收到警告:
警告FS0193:类型参数缺少约束'when(^ a或^?23604):( static> member(+):^ a*^?23604 - > ^?23605)'
在最后一行的"更长"一词.据我所知,它应该能够推断它总是添加'a'的两个成员.我怎么能摆脱这个?
这是一个有趣的问题,使用let绑定函数而不是静态成员似乎不会触发相同的警告。据推测,letbound 和成员函数中静态类型参数的解析之间存在差异。
module PolyAdder =
    let inline addPoly x y = 
        match x,y with
        |Polynomial xlist, Polynomial ylist ->
            let (longer : ^a list), (shorter : ^a list) = 
                if xlist.Length > ylist.Length then xlist, ylist
                else ylist, xlist
            let shorterExtended : ^a list = shorter @ (List.init (longer.Length - shorter.Length) (fun _ -> LanguagePrimitives.GenericZero< ^a >))
            // no warning here!
            List.map2 (+) longer shorterExtended |> Polynomial
Run Code Online (Sandbox Code Playgroud)
然后,您可以Polynomial基于上面的 let 绑定函数使用 + 运算符进行扩展:
type Polynomial with
    static member inline (+) (x, y) = PolyAdder.addPoly x y
Run Code Online (Sandbox Code Playgroud)
仍然没有警告,+运算符工作正常
let poly1 = [1; 2; 5; 6; 8] |> Polynomial
let poly2 = [7; 1; 2; 5;] |> Polynomial
let polyAdded = poly1 + poly2
Run Code Online (Sandbox Code Playgroud)