F#: можно ли динамически привязывать единицы измерения во время выполнения?
Я очень новичок в F# и заинтригован функциональностью единиц измерения и имею приблизительное представление о том, как это работает обычно, но хотел бы знать, возможно ли привязать меры к значениям, где мы не знаем, какой будет мера, пока код не выполняется?
Практический пример, который я рассматриваю, - это привязка поплавков как значений валюты, где единица измерения выводится из поиска в базе данных.Предположим, что меры для каждой валюты (USD, EUR, AUD, etc) объявляются обычно:
[<Measure>] USD
[<Measure>] EUR
[<Measure>] AUD
...
Во-первых, вам понадобится способ получить тип меры из идентификатора, в идеале само имя меры, поскольку код валюты, скорее всего, хранится и извлекается в виде 3-символьной строки (аналогично Enum.Parse()
).
Тогда вам понадобится способ привязки значения float к типу, созданному на предыдущем шаге.
Возможно ли это, или есть другой способ достичь того же результата?2 ответа:
Это невозможно, так как единицы измерения F# стираются (они существуют только во время компиляции).
Вы можете создать библиотеку с реализацией во время выполнения (я не думал о том, как будет выглядеть дизайн). Но вы, вероятно, потеряете статическую проверку.
Я думаю, что, возможно, лучшей стратегией может быть изолировать границу, и в пограничной точке (где вы читаете из базы данных и выводите типы единиц) каким-то образом получить правильные типы в системе типов, но в зависимости от того, как вы это делаете. от того, как структурирован код и что именно вы делаете, это может быть или не быть возможным/легким...
Если вы не пишете код, который на самом деле специфичен для одной конкретной валюты, вы не должны явно упоминать USD, EUR, AUD и т. д. В своем коде. Вместо этого сделайте свой код полиморфным по отношению к соответствующей валюте/валютам.
Вам следует подумать о том, какого рода безопасность вы ожидаете получить от единиц измерения. Если, например (в очень упрощенном сценарии) вы читаете из поля базы данных, выполняете некоторую обработку и записываете обратно в это же поле, то наличие функции типаfloat<'a> -> float<'a>
- это именно то, что вам нужно: вам все равно, какая валюта, пока вы получаете обратно ту же самую, которую вы положили.