Это достаточно легко конвертировать единицы измерения к типу базового значения и обратно:Определение общего преобразования и из единиц измерения в F # для их основных типов
[<Measure>]
type meter
module Meter =
let from m = m * 1</meter>
let too m = m * 1<meter>
Но потом я подумал, не так ли быть прекрасным, чтобы преобразовать из одного базового типа в блок измерения и обратно, в общем? Конечно, я могу на каждом конкретном случае быть конкретным, но я решил, что было бы удобно иметь оператора броска и литья, сохраняя при этом безопасность типов.
Моя первая попытка:
[<AutoOpen>]
module Convert =
let inline (!->) x = x * 1<_> // (often) magically works
let inline (!-<) x = x * 1</_> // syntax error on the "/_"
В !->
работает оператор в силу умозаключений типа. Было бы неплохо, если бы второй оператор тоже работал, но /_
не поддерживается синтаксисом. Я попробовал несколько типов аннотированных вариантов, но не смог найти прямое общее решение, отчасти потому, что мы не можем писать 'T<'M>
или их вариант.
Я тогда думал использовать трюк, используемый для неявных преобразований, но применительно к явным преобразованиям, так как основной типа 'T<'M>
если 'T
и всегда существует явное приведение:
[<AutoOpen>]
module Convert =
let inline explicit_convert (x:^a) : ^b = ((^a or ^b) : (static member op_Explicit : ^a -> ^b) x)
let inline (::>) x = explicit_convert x // works both ways
Это имеет дополнительное преимущество, что он работает на любом типе, который имеет явный оператор преобразования. К сожалению, компилятор жалуется, что не может быть безопасно сделать так:
ограничение членов с именем «» op_Explicit приведены особого статуса на F # компилятора, как некоторые .NET типы неявно дополненный с этим элементом. Это может привести к сбоям во время выполнения, если вы попытаетесь вызвать ограничение члена из вашего собственного кода.
Я не уверен, что я нахожусь на правильном пути или существует ли более безопасный тип создания оператора, который может перейти от любого измерения к базовому типу и обратно (включая сложные измерения, например int<meter^4>
или int<meter/sec^2>
)
Спасибо, это выглядит многообещающе. Я не знаком с синтаксисом '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '? Это что-то автоматическое отображение Du? – Abel
@Abel $ - это просто выбор латынь, сделанный для его пользовательского оператора (он мог бы выбрать (+), если бы захотел).Он сделал такой выбор, чтобы подражать «приложению» оператора в Haskell (см. [Здесь] (http://stackoverflow.com/a/19521376/4925216)) – Sehnsucht
Первая часть была уже в [предыдущем ответе] (http: /stackoverflow.com/questions/28786971/generic-units-in-f/28787251#28787251). Тот факт, что вы предложили точно такой же код, заставляет меня думать, что он определенно должен быть частью библиотеки F #;) – Gustavo