oft sehr, wenn generischen Code in F # Schreiben komme ich von einer ähnlichen Situation wie diese (ich weiß, das ziemlich ineffizient, nur zu Demonstrationszwecken ist):Wie kann ich einen Wert auf einen Typ zurückgeben, den ein Wert zuvor hatte?
let isPrime n =
let sq = n |> float |> sqrt |> int
{2..sq} |> Seq.forall (fun d -> n % d <> 0)
Für viele Probleme kann ich statically resolved types verwenden und erhalte sogar ein Leistungsschub durch Inlining.
let inline isPrime (n:^a) =
let two = LanguagePrimitives.GenericOne + LanguagePrimitives.GenericOne
let sq = n |> float |> sqrt |> int
{two..sq} |> Seq.forall (fun d -> n % d <> LanguagePrimitives.GenericZero)
Der obige Code wird nicht kompiliert, da die obere Sequenzgrenze ein Float ist. Nongenerisch könnte ich zum Beispiel einfach auf int
zurückwerfen.
Aber der Compiler wird mich nicht davon verwenden lassen:
let sq = n |> float |> sqrt :> ^a
let sq = n |> float |> sqrt :?> ^a
und diese beiden führen zu einem InvalidCastException
:
let sq = n |> float |> sqrt |> box |> :?> ^a
let sq = n |> float |> sqrt |> box |> unbox
Auch upcast
und downcast
sind verboten.
let sq = System.Convert.ChangeType(n |> float |> sqrt, n.GetType()) :?> ^a
funktioniert, scheint mir aber sehr umständlich.
Gibt es einen Weg, den ich übersehen habe oder muss ich wirklich die letzte Version verwenden? Denn der letzte wird auch für bigint
brechen, was ich ziemlich oft brauche.
Ich habe ein bisschen herumgespielt und die beste Lösung, die ich mir ausgedacht habe, war die Kernbibliothek zu modifizieren. Wenn Ihnen die Leistung nicht besonders wichtig ist, können Sie die Nummer immer durch Hinzufügen von Zweierpotenzen aufbauen. –
Warum müssen Sie vor dem Aufruf von 'sqrt' in' float' umwandeln? – Daniel
@Daniel weil Sie (zB) kein int an sqrt übergeben können: 'Der Typ 'int' unterstützt nicht den Operator 'Sqrt'' – phoog