Closed idontgetoutmuch closed 7 years ago
I think you are defining your unit the way you are supposed to define units, generally speaking, although @dmcclean would have to confirm that. What you are doing is defining a new unit in terms of another unit, in this case, 1 siUnit
, which happens to be 1 mol
with your chosen dimension.
The behaviour
*Main> 1 *~ iUepo
1.0 mol
is correct and expected given your definitions. The Show
instance for quantities always shows them with their SI unit. For example, you will see that:
*Numeric.Units.Dimensional.Prelude> 1 *~ becquerel
1 s^-1
If you want something else than the SI Unit you can use showIn
:
*Numeric.Units.Dimensional.Prelude> showIn becquerel $ 1 *~ becquerel
"1.0 Bq"
I think that addresses half of your question. The other half is trickier because you want to use a unit does not have a direct correspondence to an SI unit (as far as I understand, but I am no biologist either). I think there are a few ways you could define your IUEPO, but which one is appropriate may depend on what you are trying to do with it.
You could define it in terms of (urinary?) “mg glycoprotein” with
iUEpo = mkUnitZ (atom "IUEPO" "IUEPO" "International Unit EPO") 0.5 (milli gram)
but this may get messy if you are using other masses.
You could define it in terms of “micromoles of cobaltous chloride” with
iUepo :: Fractional a => Unit NonMetric DAmountOfSubstance a
iUEpo = mkUnitQ (atom "IUEPO" "IUEPO" "International Unit EPO") 5 (micro mole)
but this may get messy if you are using other “amounts of substance”.
Or, you could just pick an SI dimension that you know you will never use for anything else (in combination with IUEPO) and use that:
iUEpo'' :: Num a => Unit NonMetric DLuminousIntensity a
iUEpo'' = mkUnitZ (atom "IUEPO" "IUEPO" "International Unit EPO") 1 siUnit
This is obviously a pretty ugly hack and will not play well with other/intended uses of dimensional. But it may be a practical solution if you a doing a one-off thing in a silo. (You can of course also fork dimensional and add an eighth base dimension for IU, but don't expect us to merge a pull request.)
I hope that helps somewhat.
Thanks very much for your prompt and comprehensive response :) In the end I have gone for
muPerMl :: (Fractional a, Num a) => Unit 'NonMetric DConcentration a
muPerMl = (milli mole) / (milli litre)
pretending that International Units for EPO are actually moles. A typical amount for a person would be 15.0 *~ muPerMl
. I don't have any reactions to worry about (at the moment at any rate) so I don't think I will trip over a problem mixing IUs with moles.
When I have time I will try to understand how biologically active molecules are measured. It seems each one has its own units and they can't be expressed in terms of SI units. But I may have misunderstood.
I am not a biologist say I can't say I fully understand this but substances like erythropoietin (EPO) are not measured in e.g. moles but "amounts are expressed in units (U) rather than in grams or moles, because native EPO and rhEPOs are mixtures of isoforms with differing bioactivities" (https://academic.oup.com/ndt/article/24/5/1366/1887384/Efficacy-of-recombinant-erythropoietins-is-there). So I need a new unit and I can't see a way of producing one without making a PR. If I say
then I think I can't use e.g. milli-iUs. Also I get this
when I would expect
1.0 IUEPO
.I think I need something like
becquerel
but this is defined asand I don't think
ucumMetric
is exposed.What's the best way of doing what I need?