F#: Can units of measure be bound dynamically at runtime?

孤者浪人 提交于 2019-12-10 16:59:04

问题


I'm very new to F# and am intrigued by the Units of Measure functionality and have a rough idea of how it works normally, but would like to know if it's possible to bind measures to values where we don't know what the measure will be until the code is executing?

The practical example I'm looking at is binding floats as currency values where the unit of measure is inferred from a database lookup.

Let's assume that the measures for each currency (USD, EUR, AUD, etc) are declared normally:

[<Measure>] USD
[<Measure>] EUR
[<Measure>] AUD
...

First you would need a way to obtain a measure's type from an identifier, ideally the measure name itself as the currency code is most likely stored and retrieved as a 3-character string (similar to Enum.Parse()).

Then you would need a way of binding a float value to the type created in the previous step.

Is this possible, or is there another way to achieve the same outcome?


回答1:


This isn't possible, since F# units-of-measure are erased (they only exist at compile-time).

You could author a library with a runtime implementation (I haven't thought about what a design would look like). But you probably lose the static checking.

I think possibly a better strategy may be to isolate the boundary, and at the boundary point (where you read from the database and infer the unit types) somehow get the right types into the type system, but depending on how the code is structured and what exactly you're doing, that may or may not be possible/easy...




回答2:


Unless you are writing code that is actually specific to one particular currency, you shouldn't explicitly mention USD, EUR, AUD etc in your code. Instead, make your code polymorphic over the currency/currencies involved.

What you have to think about is what kinds of safety you are expecting to get from units of measure. If for example (in a very simplistic scenario) you would be reading from a database field, doing some processing and writing back to that same field, then having a function of type float<'a> -> float<'a> is exactly what you want: you don't care what the currency is, so long as you get back the same one you put in.



来源:https://stackoverflow.com/questions/4140247/f-can-units-of-measure-be-bound-dynamically-at-runtime

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!