2011-08-22 11 views
9

Pomijając czy powinniśmy użyć jednostek miary dla niemianowana pojęć takich jak kąty, załóżmy, że mam określić degree i radian jednostek w F #Jak zdefiniować element rozszerzenia na jednostce miary F #?

type [<Measure>] degree = 
    static member ToRadians (d:float<degree>) : float<radian> = d * (Math.PI * 1.<radian>)/180.0<degree> 
and [<Measure>] radian = 
    static member ToDegrees (r:float<radian>) : float<degree> = r * 180.0<degree>/(Math.PI * 1.<radian>) 

mogę wykorzystać je stosunkowo łatwo jak

4.0<degree> |> degree.ToRadians 

Wydaje podobnie jak członkowie rozszerzenia byliby jeszcze bardziej poręczni. Więc mogę tylko powiedzieć

let d = 4.0<degree> 
let r = d.ToRadians() 

Ale nie mogę zdefiniować elementem wydłużającym oczywisty sposób

type float<degree> with 
    member degrees.ToRadians() = degree.ToRadians(degrees) 

... to robi mi się następujący błąd

error FS0010: Unexpected identifier in type name. Expected infix operator, quote symbol or other token. 

Czy istnieje sztuczka składniowa dla członków rozszerzenia na jednostkach miary w F #, lub czy ta funkcja jest obsługiwana?

+0

Zamierzam zaryzykować przypuszczenie, że nie jest obsługiwane. Wszystko, co próbowałem, spowodowało błąd: "Deklaracje miar mogą mieć tylko statycznych członków". – Daniel

+1

Problem polega na tym, że informacja o typie miary jest usuwana po kompilacji, więc w czasie wykonywania wszystko jest po prostu 'float', więc wywołanie metody instancji nie ma sensu –

+1

@jpalmer. Podczas kompilacji członkowie rozszerzenia są statycznie rozwiązywani. –

Odpowiedz

5

Elementy rozszerzenia F # różnią się od elementów rozszerzających C# tym, że nie można definiować rozszerzeń skonstruowanych typów ogólnych. Na przykład możesz zdefiniować rozszerzenia na seq<'t>, ale nie na seq<int>. Innymi słowy, członkowie rozszerzenia działają raczej jak członkowie typu, niż statyczne. Odnosi się do pomiaru typów zbyt, więc nie można określić rozszerzenie na float<degree>, ale można określić rozszerzenie na float<[<Measure>]'u>:

type float<[<Measure>]'u> with 
    member f.Squared() = f * f 

[<Measure>] 
type m 

let area = 2.0<m>.Squared() 

Jednak nie widzę jak to pomaga w Twoim przypadku ..

+0

To ma sens. Nie ma żadnej realnej korzyści z definiowania tych metod rozszerzenia innych niż składnia, a jest mnóstwo innych dobrych opcji. –

Powiązane problemy