Im folgenden Code möchte ich eine Template-Klasse mit dem Typ einer Variablen instanziieren, letztlich als generische Variable, die in eine Funktion übergeben wird, aber selbst diese einfachere Form funktioniert nicht:Verwendung von ableitbaren Typen zur Kompilierzeit in F # -Templates
type saveXY<'a when 'a:comparison> (x:'a,y:'a) =
member this.X = x
member this.Y = y
member this.lessThan() = this.X < this.Y
[<EntryPoint>]
let main argv =
let x1 = 3
let y1 = 7
let saver1 = new saveXY<int>(x1,y1) // Good
printfn "%A" (saver1.lessThan())
let x2 = 3.0
let y2 = 7.0
let saver2 = new saveXY<float>(x2,y2) // Good
printfn "%A" (saver2.lessThan())
let saver3 = new saveXY<x2.GetType()> (x2,y2) // No Good, see errors
0
jedoch für saver3
unten ich (und ich kann Informationen über FS1241 finden):
...\Program.fs(23,39): error FS0010: Unexpected symbol '(' in type arguments. Expected ',' or other token.
...\CompareProblem\Program.fs(23,39): error FS1241: Expected type argument or static argument
Wenn Sie das Templat auf saveXY
entfernen, dann ist saver2
irrtümlich als saver1
die 012 verursachtKlassenargumente, die auf Ints beschränkt sein müssen.
Ich experimentierte auch mit deklarieren x und y als einfach obj
, aber das funktioniert nicht. Ich vermute, dass das Problem ist, dass dies einfach, dass dies nicht möglich ist, das heißt, wenn die Klassenargumenttypen generisch sind, werden sie einmal abgeleitet (von der ersten Verwendung). Auf der anderen Seite, vielleicht verpasse ich etwas.
Gibt es eine Möglichkeit, Variablen-basierte Typen zu verwenden, die zur Kompilierzeit als Typvorlagenargumente in F # definiert werden könnten? Gibt es eine andere Möglichkeit, einen Typ zu erstellen, der generische Werte verarbeiten/speichern kann?
UPDATE: Von Lee Vorschlag, das funktioniert, wenn Sie die Vorlage Klasse und dann nur <_>
es zu instanziiert verwenden funktioniert:
type saveXY<'a when 'a:comparison> (x:'a, y:'a) =
member this.X = x
member this.Y = y
member this.lessThan() = this.X < this.Y
[<EntryPoint>]
let main argv =
let x1 = 3
let y1 = 7
let saver3 = new saveXY<_> (x1,y1) // works, 'a is int
printfn "%A" (saver3.lessThan())
let x2 = 3.0
let y2 = 7.0
let saver3 = new saveXY<_> (x2,y2) // works, 'a is float
printfn "%A" (saver3.lessThan())
System.Console.ReadKey() |> ignore // wait for a key
0
Aber warum muss ich den Klassentyp als Templat, wie Ich schlug oben vor? Es scheint, dass der Compiler die Typen ohnehin herzuleiten wenn ich <_>
also warum kann ich nicht einfach (wie ich würde für eine Funktion):
type saveXY(x, y) = // x and y are generic, no? They only require comparison, yes?
member this.X = x
member this.Y = y
member this.lessThan() = this.X < this.Y
[<EntryPoint>]
let main argv =
let x1 = 3
let y1 = 7
let saver3 = new saveXY (x1,y1) // works
printfn "%A" (saver3.lessThan())
let x2 = 3.0
let y2 = 7.0
let saver3 = new saveXY (x2,y2) // But this FAILS with error FS0001
printfn "%A" (saver3.lessThan())
System.Console.ReadKey() |> ignore // wait for a key
0
Nein, Sie können keine Typparameter wie diesen angeben, obwohl Sie den Typ von 'x2' und' y2' bereits statisch kennen, daher ist Ihr Anwendungsfall nicht klar. – Lee
Nicht sehr klar, was genau du zu tun versuchst: Versuchst du Code zu erstellen, der deine Klasse mit einem generischen Argument instanziiert, das zum Kompilierungszeitpunkt nicht bekannt ist, oder willst du einfach sagen: "welcher Typ auch immer?" benutze bitte that_ ", und der Compiler hat es herausgefunden? –
Es ist: _simply will sagen "welcher Typ x2 ist, bitte verwenden Sie das", und Compiler haben es herauszufinden? _ Fall - in dem obigen Beispiel möchte ich 'saver3' mit einem Float-Template-Typ instanziiert werden, da 'x2' ist ein Float. Im realen Code wird x2 ein Funktionsargument vom generischen Typ sein, aber wo die Funktion mit verschiedenen Kompilierzeittypen instanziiert wird – user1857742