F#: можно ли динамически привязывать единицы измерения во время выполнения?


Я очень новичок в F# и заинтригован функциональностью единиц измерения и имею приблизительное представление о том, как это работает обычно, но хотел бы знать, возможно ли привязать меры к значениям, где мы не знаем, какой будет мера, пока код не выполняется?

Практический пример, который я рассматриваю, - это привязка поплавков как значений валюты, где единица измерения выводится из поиска в базе данных.

Предположим, что меры для каждой валюты (USD, EUR, AUD, etc) объявляются обычно:

[<Measure>] USD
[<Measure>] EUR
[<Measure>] AUD
...
Во-первых, вам понадобится способ получить тип меры из идентификатора, в идеале само имя меры, поскольку код валюты, скорее всего, хранится и извлекается в виде 3-символьной строки (аналогично Enum.Parse()).

Тогда вам понадобится способ привязки значения float к типу, созданному на предыдущем шаге.

Возможно ли это, или есть другой способ достичь того же результата?
2 4

2 ответа:

Это невозможно, так как единицы измерения F# стираются (они существуют только во время компиляции).

Вы можете создать библиотеку с реализацией во время выполнения (я не думал о том, как будет выглядеть дизайн). Но вы, вероятно, потеряете статическую проверку.

Я думаю, что, возможно, лучшей стратегией может быть изолировать границу, и в пограничной точке (где вы читаете из базы данных и выводите типы единиц) каким-то образом получить правильные типы в системе типов, но в зависимости от того, как вы это делаете. от того, как структурирован код и что именно вы делаете, это может быть или не быть возможным/легким...

Если вы не пишете код, который на самом деле специфичен для одной конкретной валюты, вы не должны явно упоминать USD, EUR, AUD и т. д. В своем коде. Вместо этого сделайте свой код полиморфным по отношению к соответствующей валюте/валютам.

Вам следует подумать о том, какого рода безопасность вы ожидаете получить от единиц измерения. Если, например (в очень упрощенном сценарии) вы читаете из поля базы данных, выполняете некоторую обработку и записываете обратно в это же поле, то наличие функции типа float<'a> -> float<'a> - это именно то, что вам нужно: вам все равно, какая валюта, пока вы получаете обратно ту же самую, которую вы положили.