2015-12-23 13 views
6

ich die folgende Art definiert haben (von Code vereinfacht):Typ-Inferenz auf generische Art mit statisches Element Einschränkung andernfalls

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 

Wenn ich baue ich die Warnung erhalten:

Warnung FS0193: A Typ Parameter fehlen eine Einschränkung 'wenn (^ a oder^23604?): (static> Glied (+):??^a *^23604 ->^23605)'

auf dem Wort "mehr" in der letzten Zeile. Soweit ich sehen kann, sollte es in der Lage sein zu folgern, dass es immer zwei Mitglieder von a hinzufügt. Wie kann ich das loswerden?

Antwort

3

Dies ist eine interessante Frage, mit einer let gebundenen Funktion anstelle eines statischen Elements scheint nicht die gleiche Warnung auszulösen. Vermutlich gibt es Unterschiede zwischen der Auflösung von statischen Typparametern in gebundenen und Elementfunktionen.

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 

Sie dann Polynomial mit einem Operator + basiert auf dem let gebunden Funktion oben erweitern können:

type Polynomial with 
    static member inline (+) (x, y) = PolyAdder.addPoly x y 

Es gibt noch keine Warnung und der Operator + arbeitet normalerweise

let poly1 = [1; 2; 5; 6; 8] |> Polynomial 
let poly2 = [7; 1; 2; 5;] |> Polynomial 
let polyAdded = poly1 + poly2 
+0

Nizza Abhilfe . – FZed

Verwandte Themen