Как определить элемент расширения в единице измерения F#?

Не говоря уже о том, должны ли мы использовать единицы измерения для безразмерных понятий, таких как углы, предположим, что я определил degree и radian единицы измерения в 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# или поддерживается ли эта функция?


person Sebastian Good    schedule 22.08.2011    source источник
comment
Рискну предположить, что он не поддерживается. Все, что я пробовал, выдавало ошибку: Measure declarations may have only static members.   -  person Daniel    schedule 23.08.2011
comment
Проблема в том, что информация о типе меры удаляется после компиляции, поэтому во время выполнения все представляет собой просто float, поэтому вызов метода экземпляра не имеет смысла.   -  person John Palmer    schedule 23.08.2011
comment
@jpalmer. Во время компиляции члены расширения разрешаются статически.   -  person Sebastian Good    schedule 23.08.2011
comment
@Sebastion Хорошо - точно, после проверки типа дополнительная информация о типе удаляется, и ваш код просто скомпилирован для операций со стандартными floats   -  person John Palmer    schedule 23.08.2011


Ответы (1)


Члены расширения 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()

Однако я не вижу, как это поможет вам в вашем случае...

person kvb    schedule 23.08.2011
comment
Это имеет смысл. Нет никакой реальной пользы от определения этих методов расширения, кроме синтаксиса, и есть много других хороших вариантов. - person Sebastian Good; 23.08.2011