2009-10-01 8 views
9

Zastanawiałem się, w jaki sposób można zapisać zdefiniowaną przez użytkownika funkcję pierwiastkowania kwadratowego (sqrt) w sposób, który współdziała on poprawnie z F # 's unit system.Bezpieczne jednostki o kwadratowych korzeniach

Co powinno być tak:

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

Ale to jest niedozwolone ze względu na niezerowe stałe nie pozwolono mieć jednostki rodzajowe.

Czy istnieje sposób napisania tej funkcji? Z wbudowanym sqrt działa dobrze, więc jaka magia to działa?

+1

Powiązane pytanie: (również odpowiedział @kvb) http://stackoverflow.com/questions/1398611/f-ununit-reunit-inside-a-function – Benjol

Odpowiedz

6

Dopuszczenie niezerowych stałych ogólnych bardzo ułatwiłoby złamanie zabezpieczeń systemu typu dla jednostek (patrz Andrew Kennedy's papers). Wierzę, że odpowiedź na twoje ostatnie pytanie jest taka, że ​​sqrt jest w istocie magią w pewnym sensie, że nie powinno być możliwe zdefiniowanie funkcji parametrycznej z podpisem tego typu w normalny sposób. Jednakże jest można robić, co chcesz (przynajmniej w obecnej wersji F #), korzystając z boksu i rzucania:

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

@kvb ma rację, bardziej ogólnie:

Jeśli masz algorytm nie będący jednostką świadomą (np. mówisz, że piszesz "pierwiastek kostki"), i chcesz umieścić jednostki na nim, możesz zawinąć algorytm w funkcji z odpowiednim podpisem typu i użyć np. "unosić się", aby "odrzucić" jednostki, gdy przychodzą, oraz podejście "pole do dołu", aby "dodać" odpowiednie jednostki po drodze.

W wydaniu RTM (po Beta2), F # będzie mieć pierwotne funkcje biblioteczne dla "jednostek dodawania", ponieważ podejście "pole do dołu i dołu" jest obecnie trochę hackem do przezwyciężenia braku tych prymitywów w język/biblioteka.

+0

Dzięki - Czy mógłbyś wymienić te nowe funkcje biblioteki (Link)? – Dario

+3

Zostaną one prawdopodobnie nazwane np. "val inline FloatWithMeasure: float -> float <'u>" w module LanguagePrimitives. – Brian

+0

A oto: http://msdn.microsoft.com/en-us/library/ee806527(VS.100).aspx – Benjol

Powiązane problemy