2009-10-01 4 views
9

Ich frage mich, wie es möglich ist, eine benutzerdefinierte Quadratwurzelfunktion (sqrt) so zu schreiben, dass sie mit F # unit system richtig interagiert.Einheitssichere Quadratwurzeln

Was es sein sollte wie:

 
let sqrt (x : float<'u^2>) = 
    let x' = x/1.0<'u^2> // Delete unit 
    (x ** 0.5) * 1.0<'u>  // Reassign unit 

Aber dies aufgrund Nicht-Null-Konstanten nicht erlaubt ist nicht generische Einheiten haben dürfen.

Gibt es eine Möglichkeit, diese Funktion zu schreiben? Mit dem eingebauten sqrt funktioniert es gut, also welche Magie führt es aus?

+1

Verwandte Frage: (auch beantwortet von @ kvb) http://StackOverflow.com/Questions/1398611/F-Ununit-Reunit-inside-a-Funktion – Benjol

Antwort

6

Wenn Sie generische Konstanten ungleich Null zulassen, ist es sehr einfach, die Sicherheit des Typsystems für Einheiten zu unterbrechen (siehe Andrew Kennedys papers). Ich glaube, dass die Antwort auf Ihre letzte Frage ist, dass sqrt in der Tat magisch in der Hinsicht ist, dass es nicht möglich sein sollte, eine parametrische Funktion mit dieser Art Unterschrift durch normale Mittel zu definieren. Es ist jedoch ist möglich zu tun, was man (zumindest in der aktuellen Version von F #) will durch die Nutzung von Boxen nehmen und Gießen:

let sqrt (x : float<'u^2>) = 
    let x' = (float x) ** 0.5 (* delete unit and calculate sqrt *) 
    ((box x') :?> float<'u>) 
6

@kvb ist richtig, allgemeine:

Wenn Sie haben einen nichteinheitsbewußten Algorithmus (zB sagen Sie, Würfelwurzel '), und Sie wollen Einheiten auf ihn setzen, Sie können den Algorithmus in eine Funktion mit der richtigen Typsignatur einschließen und zB verwenden "schweben", um die Einheiten "wegzuwerfen", sobald sie eintreffen, und den "Box-and-Downcast" -Ansatz, um die entsprechenden Einheiten auf dem Weg nach draußen "hinzuzufügen".

In der RTM-Version (nach Beta2) wird F # primitive Bibliotheksfunktionen für die 'add back units' haben, da der Box-and-downcast-Ansatz derzeit ein bisschen ein Hack ist, um das Fehlen dieser Primitiven zu überwinden die Sprache/Bibliothek.

+0

Danke - Könnten Sie diese neuen Bibliotheksfunktionen (Link) nennen? – Dario

+3

Sie werden wahrscheinlich z. "val Inline FloatWithMeasure: float -> float " im Modul SprachPrimitive. – Brian

+0

Und hier ist es: http://msdn.microsoft.com/en-us/library/ee806527(VS.100).aspx – Benjol