2011-08-22 60 views
9

撇開我們是否應該使用的測量單位,像角無單位的概念,假設我有定義degreeradian單位在F#如何在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>) 

我可以比較輕鬆地使用他們喜歡

4.0<degree> |> degree.ToRadians 

似乎像擴展成員會更加輕鬆。所以我還是說

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

但我不能確定延長部件的明顯的方式

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

...這讓我下面的錯誤

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

是否有F#中度量單位的擴展成員的語法技巧,還是支持的功能?

+0

我會冒險猜測它不被支持。我試過的所有東西都給出了錯誤:'度量聲明可能只有靜態成員'。 – Daniel

+1

問題是編譯後刪除了度量類型信息,所以在運行時一切都只是一個'float',因此調用一個實例方法沒有意義 –

+1

@jpalmer。在編譯期間,擴展成員是靜態解析的。 –

回答

5

F#擴展成員與C#擴展成員不同,因爲您無法定義構造的泛型類型的擴展。例如,您可以在seq<'t>而不是seq<int>上定義擴展名。換句話說,擴展成員的行爲類似於類型的成員,而不是靜態方法。這適用於測量類型的,所以你不能在float<degree>定義一個擴展,但你可以在float<[<Measure>]'u>定義一個擴展:

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

[<Measure>] 
type m 

let area = 2.0<m>.Squared() 

不過,我看不出這可以幫助你在你的情況..

+0

這很有道理。除了定義語法之外,定義這些擴展方法並沒有真正的好處,還有很多其他的好選擇。 –