bjornbm / dimensional Goto Github PK
View Code? Open in Web Editor NEWDimensional library variant built on Data Kinds, Closed Type Families, TypeNats (GHC 7.8+).
License: BSD 3-Clause "New" or "Revised" License
Dimensional library variant built on Data Kinds, Closed Type Families, TypeNats (GHC 7.8+).
License: BSD 3-Clause "New" or "Revised" License
Given that Angle
already names the type of arbitrary angles, what is the best name for the type of angles that are constrained to lie within a single revolution? (Alternately, the type of angles that are equated if they differ by an integer number of turns.)
Both types are all over the place.
We should keep Angle
for the one it denotes now, for consistency with the way we treat Time
and Temperature
and so forth as unbound from any particular distinguished origin.
Are there any objections to setting up this repository to use travis-ci?
Because it's open source, it's free, and their server will automatically run the build and tests (once we fix them) after each commit. It also runs it on each PR so that you can see whether merging it will break the build before you decide.
I can set up the configuration, but only the repository owner can actually turn it on. As a result, @bjornbm would need to sign up for an account on travis-ci.org using his github account and grant certain permissions to their servers.
If we decide to do this you can sign up at any time, but probably shouldn't flip the on switch until we have the configuration file in place.
Example: (where this issue is already flagged)
type family a * b where -- constrain kinds??
(Dim l m t i th n j) * (Dim l' m' t' i' th' n' j')
= Dim (l + l') (m + m') (t + t') (i + i') (th + th') (n + n') (j + j')
On my reading of the relevant docs, that the correct kind (Dim -> Dim -> Dim
) will be inferred for closed type family declarations of this form. I can't confirm this because my GHC 7.8 install isn't working yet.
Nevertheless it might be desirable to write them out explicitly for the sake of new readers.
In #29 and #19 we discussed whether the Dimensional
constructor should be exposed, and whether to have a Functor
instance.
We came down on the side of no, which I strongly agree with, because it breaks the abstraction. We exposed dmap
from DK
but not DK.Prelude
so that people could get at this if they wanted to, but wouldn't get it by default.
I now propose that we add a Functor
instance, but put it in a separate module.
{-# LANGUAGE OverlappingInstances #-}
{-# OPTIONS_GHC -fno-warn-orphan-instances #-}
module Numeric.Units.Dimensional.DK.DubiousFunctorInstance where
import Numeric.Units.Dimensional.DK
instance Functor (Dimensional v d) where
fmap = dmap
The purpose of this is to empower users to make the choice for themselves. One specific reason for making such a choice would be to be able to get along with Edward's linear package.
For some of the legacy units it would be nice to have functionality like that of (/~)
which in some sense "splits" a quantity into multiple units.
Something like:
split :: (RealFrac a, Integral b) => (Unit d a, Unit d a) -> Quantity d a -> (b, a)
split (a, b) x = -- something that involves properFraction
so that split (foot, inch) (12.37 *~ meter)
evaluates to (40, 7.00787)
because 12.37 meters is 40 feet 7.00787 inches.
Also would like the same thing but for triples, split3 :: (RealFrac a, Integral b) => (Unit d a, Unit d a, Unit d a) -> Quantity d a -> (b, b, a)
for converting to degrees/minutes/seconds of arc.
One hairy thing is that it's unclear what the semantics should be when the second unit is larger than the first. I suppose it makes some sense to allow split (foot, mile) (12.37 *~ meter)
to be (40, 0.000110604)
. Nobody would ever want to do it on purpose, but it isn't actually wrong.
It's possible to imagine a flavor of this library where the Variant concept is eliminated, there are only quantities, and units don't exist.
It seems like this would be simplifying and desirable, except for two things:
*~
and /~
anymore, because 6.3 * meter
now promotes the 6.3 to (Fractional a) => Dimensionless a
, and meter is (Num a) => Quantity DLength a
.extractValue :: Dimensionless a -> a
(or unD
or something) is possible. But is the noise of that worth the benefits of getting rid of unit vs quantity?coerce
function already this elimination operator? I think it might be, because all the hypothetical extractValue
function does is unwrap the newtype.kilo
and friends to apply to general quantities.There are a lot of pros and cons, so it almost feels like a coin flip.
The fact that units might have an important static role to play (in constructing useful fixed-point quantities) is another thing to consider.
Figure out how to make the instructions at http://docs.travis-ci.com/user/migrating-from-legacy/?utm_source=legacy-notice&utm_medium=banner&utm_campaign=legacy-upgrade mesh with the instructions we followed to get multiple GHC versions working.
Electricians in the US use a fairly bizarre unit called the circular mil, defined to be the area of a circle one mil in diameter. (A mil, in turn, being 1e-3 inches.)
We have square
and cubic
. Logically circular
could be in the same category, which would be consistent. But I've also never heard of anyone else anywhere on earth using circular anything-besides-mil as a unit.
It's basically pi / 4 times whatever square
would give you.
What is the policy on documentation style?
Right now we have some .lhs
files written in a bird-tack markdown style and some .hs
files with markdown in block comments.
Are you using pandoc to process the markdown into something? If so, can you share a script for invoking it as you do so that contributors can be sure not to break it?
It's presumably desirable to have haddock comments as well. Or is it? If so, how do we make those coexist with the literate markdown? I tried researching this and found this StackOverflow question. The answers are informative and interesting, but AFAICT don't actually answer the most direct part of the question, which I would phrase as "what is the example syntax of a haddock commented declaration that will be acceptable to both haddock and the literate markdown processor?".
(Warning, this is a doozy.)
It would be really nice if we had a type checker plugin capable of solving constraints like d ~ DOne / (DOne / d)
and other "obvious" proof obligations that arise.
These sorts of things were crippling to the first attempt at using this for dimensional linear algebra, and especially for dimensional linear algebra as it applies to control theory. (Some of those sketches using dimensional-dk are no longer visible in history at that link.)
It turns out that unification in abelian groups (like the group of dimensions) is decidable, and that unification discharges all of these things that we think are obvious, and a few more besides. The agum package provides a Haskell implementation (unfortunately with GPL licensing) of this that could be used to do "the hard part" of this problem. Of course, the actual hard part is figuring out how the GHC type checker plugin API works. ;)
It seems that every link to Pos1
of the documentations on Hackage tries to link to c:/Users/Doug/AppData/Local/GitHub/PortableGit_c2ba306e536fdf878271f7fe636a147ff37326ad/package/numtype-dk-0.5/docs/Numeric-NumType-DK-Integers.html#v:Pos1
; the same goes for Zero
, etc.
See #27.
There seems to be some dispute over the value of the millimeter of mercury column.
prefix 13.5951 (gram * centi meter ^ neg3 * milli meter * gee)
Table 18: Units Used Predominantly in Clinical Medicine meter:
meter of mercury column = 133.3220 kPa
so mmHg = 133.3220 Pa
Table 9: Other non-SI units accepted for use with the SI either by the CIPM and this Guide (indicated by_), or by this Guide (indicated by_*)
mmHg = 133.322 Pa
A millimeter of mercury is a manometric unit of pressure, formerly defined as the extra pressure generated by a column of mercury one millimetre high and now defined as precisely 133.322387415 pascals. [1]
(seriously? 12 places? 😡)
I assume we agree that the BSI can pound sand? I'd like to match the UCUM definition so that our parser can be compliant, thankfully they agree with NIST.
The *~
operator basically converts its first argument into a dimensionless quantity and then calls the *
operator.
The /~
operator basically does \
and then strips the Dimensional
constructor off the dimensionless result.
Unfortunately there is no operator that converts its second argument into a dimensionless quantity and then calls the \
operator. flip $ (*~) . recip
, but with a type that doesn't require a Unit
the way that *~
(somewhat unfortunately, see the named-units branch) does. And I am having trouble coming up with a name for it that makes sense and aligns with the existing two.
Not having this operator seems to account for the lion's share of my use of _2
, _3
, etc. (Not _1
, and _0
, which are good for a thousand other things.)
Pursuant to the comment above about the type of *~
: If the named-units branch is too radical, how do you feel about relaxing the type of *~
from:
(*~) :: Num a => a -> Unit d a -> Quantity d a
x *~ Dimensional y = Dimensional (x Prelude.* y)
to
(*~) :: Num a => a -> Variant v d a -> Quantity d a
x *~ Dimensional y = Dimensional (x Prelude.* y)
Right now we have Eq
and Ord
instances for Dimensional
, so we have one for Ord a => Unit d a
.
Is this desirable or objectionable? AFAICS, the NIST guide doesn't say anything about it one way or the other.
(Asking because it isn't automatic in the land of named units.)
Now that Foldable
is in the prelude, can we generalize dimensionlessLength :: Num a => [Dimensional v d a] -> Dimensionless a
to (Foldable f, Num a) => f (Dimensional v d a) -> Dimensionless a
?
Following on to #7, the flip side to pretty-printing is parsing.
Unfortunately the SI unit notation and names have several ambiguities, documented (perhaps not extensively) by this article.
Nevertheless, we need not let that discourage us. We can either pick conventions, or report the ambiguities if the arise, or disambiguate them because we know what dimension we were expecting the user to enter in that field, or some combination of those strategies.
AFAICS we don't have a dimension alias for translational momentum, only for angular momentum. It's the same as the one currently called DImpulse
.
Can I add an alias or am I missing a reason why this is a bad idea?
The NIST Guide uses "moment of force", and so dimensional correctly follows that name.
I think that the name "torque" is also commonly used for the same concept, and that it would improve discoverability for new users if this name was also acceptable.
I therefore propose the addition of the following alias:
type Torque = MomentOfForce
Whether to also add:
type DTorque = DMomentOfForce
... should probably follow the same decision as that for Angle, Thrust, and EnergyPerUnitMass, which is commented as up in the air at the bottom of the Quantities file. (I would vote for adding both, personally.)
Can we separate Dimension
and Dimension'
and all the type-level operators on dimensions into their own module? It would result in cleaner documentation, shorten the main module, and could be re-exported by 'Numeric.Units.Dimensional.DK' so that clients wouldn't need to care.
I don't think dimensionlessLength
really gets us much, since we have mean
?
I also think that operator sections allow fmap (*~ meter) xs
is at least as readable as xs *~~ meter
without another operator name to remember.
#2 started out being mostly about removing the distinction between quantities and units. I was reluctant then, saying:
Separating units and quantities was a very conscious decision, and one that I am quite happy with and feel has worked quite well in practice (YMMV). Converting quantities to values is performed, by necessity, very close to NIST guidelines (see 7.1 and 7.8) and I think this is a good thing.
Now, in light of e.g. #38, I'm reconsidering. Perhaps the added complexity of separating 'Quantity' and 'Unit' is not worth the extra complexity (Variant
phantom type) and occasionally convoluted workarounds (e.g. Prelude.
uses) that it can cause.
Relaxing would allow some ugly stuff:
x = kilo (meter + mile)
y = second * x
But even the current design isn't perfect with regards to NIST, allowing, e.g.:
u = kilo (kilo (meter / second))
so I'm not sure it is worth defending.
I would like to hear if you, Doug, have had any more thoughts on this topic. I know that you have actually gone even further with the distinction in the named-units branch, and imagine the impact would be treating everything as a unit (i.e. keep tracking the unit name) until multiplying with a Num
(e.g. with (*~)
).
Define the US liquid gallon, and it's various (sub)multiples.
Making a Monoid
instance for quantities doesn't suffer from the ambiguity that led to the Sum
/Product
newtypes because, unless d
is DOne
, summing is the only obvious monoid over quantities.
I therefore proposing adding a monoid instance that sums quantities.
(I will submit a patch later when I get to a computer with GHC 7.8.)
Add benchmarks measuring to make sure that the things we think are getting erased are actually getting erased in practice.
In experimental's Codata module we had:
-- Alias this dimension as DAction? Seems rarely used?
planckConstant :: (Fractional a) => AngularMomentum a
planckConstant = 6.62606957e-34 *~ (joule * second)
This definition doesn't compile under the angular branch, because of the missing radians.
Seems the correct solution would be to add DAction
and Action
to the Quantities
module? Just checking because I've never been really clear on what this constant is about, and the wikipedia page explaing action is ... perplexing.
Well, the drawback is that they are both closed. This makes it impossible to drop in a replacement system of dimensions, such as those from the CGS or Extensible modules, or to experiment with, e.g., making angles an eighth dimension.
Any thoughts on the tradeoffs?
There is a dependency on the time library to for the toDiffTime
and fromDiffTime
functions. The functions are trivial enough that the dependency probably isn't justified. I propose removing the dependency.
(We could keep the functions with the same name but relax the types to any Real
/Frac
instead of DiffTime
. The intent would hopefully be clear, but not enforcing it with the type is a bit iffy.)
Starting a new issue to not add another thread to #46.
@dmcclean wrote:
I forgot to comment on internationalisation. I think that it might be best served by going from UnitName to UCUM and allowing people to internationalize by coming back out again? Direct structural recursion on UnitName is another possibility, but our name and abbreviation choices for non-SI units are arguably less standard.
I don't follow exactly what you envisioned in the first suggestion above. But yesterday evening I also had an idea about structural recursion and have drafted the https://github.com/bjornbm/dimensional-dk/tree/typenames branch.
The most interesting modules are UnitNames and I18N, but there are also some changes elsewhere including a change of the Dimensional
type in DK.
Type level "canonical" (our arbitrary choice) unit names are attached as ASTs to Unit
s. When the unit is to be shown the type level AST is converted to a value level AST. The mechanics for this is in UnitNames.
The string representations for units and prefixes in the value level AST can then be translated to other language by use of a Map
. See I18N, which also has the non-internationalised showUnit
and showIn
.
If you load I18N you get the prelude too (right now) and can play around a little in ghci.
*Numeric.Units.Dimensional.DK.I18N> let x = 10 *~ (meter / second ^pos2)
*Numeric.Units.Dimensional.DK.I18N> x
10.0 m s^-2
*Numeric.Units.Dimensional.DK.I18N> showIn (kilo meter / second ^ pos2) x
"1.0e-2 km/s^2"
*Numeric.Units.Dimensional.DK.I18N> showIn (second ^ neg2 * kilo meter) x
"1.0e-2 s^-2 km"
*Numeric.Units.Dimensional.DK.I18N> long en_us (kilo meter / second ^ pos2)
"kilometer/second^2"
*Numeric.Units.Dimensional.DK.I18N> long en_gb (kilo meter / second ^ pos2)
"kilometre/second^2"
*Numeric.Units.Dimensional.DK.I18N> long sv_se (kilo meter / second ^ pos2)
"kilometer/sekund^2"
*Numeric.Units.Dimensional.DK.I18N> short sv_se (kilo meter / second ^ pos2)
"km/s^2"
*Numeric.Units.Dimensional.DK.I18N> showUnit (kilo meter / second * second)
"km/s*s"
*Numeric.Units.Dimensional.DK.I18N> showUnit (kilo meter / (second * second))
"km/(s s)"
*Numeric.Units.Dimensional.DK.I18N> showUnit (one * second)
"s"
*Numeric.Units.Dimensional.DK.I18N> showUnit (one / second)
"1/s"
I haven't thought through all corner cases there might be.
I haven't thought through naming very much, mostly just used what occurred to me first.
I've based the AST around your UnitName data type. The reason for Atomic
and PrefixableAtomic
eludes me but I kept them all the same as I'm sure you have thought things through. I didn't do any research either: perhaps someone (UCUM?) already has designed the perfect AST for describing unit presentation?
Most units and prefixes are missing from SIUnits, and even fewer (kilo, meter, second) are in I18N.
Does this approach have merit?
(The code could clearly use more documentation, and perhaps som restructuring in places. If it is too opaque for you to judge let me know and I'll try to document better.)
Temperatures and times present a few challenges. The SIUnits
module deals with one of them by:
fromDegreeCelsiusAbsolute :: Fractional a => a -> ThermodynamicTemperature a
fromDegreeCelsiusAbsolute x = x *~ degreeCelsius + 273.15 *~ degreeCelsius
toDegreeCelsiusAbsolute :: Fractional a => ThermodynamicTemperature a -> a
toDegreeCelsiusAbsolute x = (x - 273.15 *~ degreeCelsius) /~ degreeCelsius
I think this is not ideal because it encourages people to store absolute temperatures in ThermodynamicTemperature a
form.
Having newtype AbsoluteTemperature a = AbsoluteTemperature (ThermodynamicTemperature a)
somewhere seems like a good idea from a documentation perspective, and also allows checking conversions between various absolute scales.
Similar issues arise when tracking times, but they are even worse because the universe wasn't nice enough to supply us with an easily accessible "absolute". As a result, code with precision timekeeping needs generally requires not one but several newtypes for absolute times.
It would be nice if the core dimensional package addressed these concerns (at least the temperature one) to facilitate interoperability among other libraries developed on top of it.
I'm not sure if this can be addressed parametrically, or if it is better addressed by just laying down a pattern to be copied at each monomorphic concept where it is needed.
One possible idea (reserving comment on its merits):
newtype DimensionalTorsor (d :: Dimension) (n :: Symbol) (a :: *) = Torsor (Quantity d a)
difference :: DimensionalTorsor d n a -> DimensionalTorsor d n a -> Quantity d a
offset :: DimensionalTorsor d n a -> Quantity d a -> DimensionalTorsor d n a
type AbsoluteTemperature = DimensionalTorsor DThermodynamicTemperature "AbsoluteTemperature"
type UtcTime = DimensionalTorsor DTime "UTC"
type TaiTime = DimensionalTorsor DTime "TAI"
-- and so forth
Unfortunately this doesn't provide an opportunity for validation/canonicalization, so for example uses of offset
can result in negative AbsoluteTemperature
s. (Which, while it might make sense in itself, does not make sense as being offset from a nearby positive temperature, AFAIUI.) Typeclass pixie dust could remedy this defect, if it was thought to be worth it.
(There is a related issue for angles, where there is a commonly needed newtype that treats Angle a
values as equivalent when they are separated by an integer number of turns. Addressing that may or may not be done using similar techniques.)
@dmcclean, I've reviewed your named-units-variants branch and lite this iteration better. However, as I asked in #7 regarding the named-units branch:
Just to make sure we're on the same page: exactly what is the problem we are trying to solve (here)? To provide the UnitMap functionality? Any other goals of the named-units branch?
Can you provide a concrete use case (perhaps pseudo-code) of what named-units will enable that cannot be handled by other means (e.g. a specialised show function taking a map of desired units)? Thanks
> knot = nauticalMile / hour
Right now a couple of the files are literate haskell with markdown (I think?) comments in the bulk of the files. The others are ordinary haskell files with markdown (again, I think) comments.
One drawback to this state of affairs is that we don't have haddocks.
@bjornbm, do you have tools you use to process the markdown to create PDF or HTML documentation from files in this style? I assume such tools are out there, but I'm having trouble figuring out which if any are in active use by the community.
I'd lean towards voting for ordinary .hs
style with haddock documentation. Some of the current explanatory discourse could move to named chunks and appear at the appropriate place in the export lists. Others could sensibly be attached to individual definitions. Still others might (I'm not sure) be better demoted to ordinary comments that aren't visible in the exported documentation.
If we make the other choice, I'd vote for doing it across the board, and for writing haddocks at least for the non-obvious things.
Either way, I'm happy to do the busywork of converting to whatever style is chosen.
The NonSI module includes this definition:
imperialCup = prefix 0.5 imperialPint
and references a table in Wikipedia of imperial units of volume measure.
But the table doesn't include an entry for the cup. Is there any such unit?
It seems sensible to define it by analogy with the US customary cup (half a US customary pint). On the other hand, it isn't in the (comprehensive to a fault) Frink units file.
The current version of the NIST guide at http://physics.nist.gov/Pubs/SP811/, where the documentation links point, appears to have been updated compared to when the documentation was written.
Several tables have changed names.
Also table 3 (the part at the end that was formerly in 3b) has added the katal (1 mole/second) as a unit of "catalytic activity". Do we have a specific objection to adding this, including the unit, dimension, and quantity aliases?
See the issue and comments posted by fredhpitts at: https://code.google.com/p/dimensional/issues/detail?id=43
They have been copied below for posterity(?) as google code is going away next year.
@dmcclean feel free to add your thoughts here as well!
What steps will reproduce the problem?
What is the expected output? What do you see instead?
Expect Test.hs to compile and run successfully. Test.hs does not compile because
lumen' should be defined as
candela * steradian' not `candela / steradian' (see luminus flux entry of Table 3 at http://physics.nist.gov/cuu/Units/units.html)What version of the product are you using? On what operating system?
dimensional-tf-0.3.0.1 downloaded with cabal. Fedora 20
Please provide any additional information below.
I fully appreciate that only item 1) above is an error and that the remaining three items are a consequence of plane and solid angles being added to the list of primary dimensions. But taken as a whole, the items highlight the danger of not adding plane and solid angles to the list. Even though dimensionless, they are physical quantities with various units of measure (radian, degree, grad, steradian, square degree, etc) that can easily get lost or misused as in item 1).
Thanks for the report. I have fixed the definition of lumen
.
However, I have to decline the request for adding plane and solid angles as base dimensions. Doing so would not be consistent with the SI and I believe it would likely introduce as many problems and ambiguities as it would remove. For example, should dividing two lengths result in a Dimensionless
or a PlaneAngle
? I recommend wrapping your angles in newtypes when you are particularly concerned about mixing them up or misusing them.
Status: Fixed
The answers to "should dividing two lengths result in Dimensionless' or a
PlaneAngle" are: 1)
Dimensionless' if you have no need to know how the dimensionless number came in to being in subsequent computation.
2) A ratio of lengths if you're dealing with ratios of mass, for instance, in subsequent computation. Adding length ratios and mass ratios is as much a dimension error as adding length and mass quantities. And even addition of length ratios is meaningless if the length ratios are not on the same basis.
3) The only circumstance in which dividing two lengths should result in a PlaneAngle is when the numerator is the distance along a circle arc and the denominator is the radius length of the same circle.
Case 3 above is the exception and should be handled as such (i.e. wrapped in a function). Being consistent with SI is laudable, but ignoring the issues that are not dealt with by SI will significantly restrict the usefulness of dimensional consistency software. I think blind canceling of dimensions during multiplications and divisions is a fundamental mistake. Finesse is needed here so as to not loose valuable information.
BTW, at one time PlaneAngle and SolidAngle were recognized as secondary dimensions in SI. For whatever reason they were deprecated. That does mean they not important to implementing dimensional consistency software. I dare say you would not have made the error in the lumen implementation if SolidAngle had been rigorously accounted for by the code. Isn't the point of dimensional consistency software to prevent such errors.
Furthermore dimension consistency software needs to address vector and affine quantities which SI says nothing about.[?]
Thanks again. I appreciate you taking your time and effort writing this. I agree with you in principle, and you are absolutely correct that the error in lumen would have been avoided if SolidAngle was tracked in it's own base dimension.
On the other hand I don't think it is an easy problem to solve, with an obvious implementation and API. As you say: finesse is needed to make it work well. But if you are willing to help draft one we could consider adding it.
FYI current and future development of dimensional is being performed on the not-yet-on-hackage dimensional-dk (https://github.com/bjornbm/dimensional-dk) that is intended to supersede dimensional and dimensional-tf. Nowadays my co-maintainer Douglas McClean (https://github.com/dmcclean) actually does most of the work on improving and expanding functionality, and he is quite sympathetic with your concerns. If you are interested in contributing I suggest that you continue the discussion of what a possible implementation could look like with him on Github while I follow from the side-lines. I've copied our conversation here to #72 for further discussion.
We have, choosing one example arbitrarily:
pascal :: Fractional a => Unit DPressure a
pascal = newton / meter ^ pos2
But we could have:
pascal :: Num a => Unit DPressure a
pascal = siUnit
because we know that, as a coherent unit, it's value is 1
. The cost is a less self-explanatory definition, which could be addressed by comments?
(This question arises more acutely in the branch that tracks exact conversion factors, but even without that feature it is an interesting question IMO.)
Following on to #5, it would be nice to have a term-level representation for units that binds the dimension, value, abbreviated name, and full name.
Suppose this type is something like (though there are probably better names):
type UnitValue (d :: Dimensions) = forall a.(Num a) => Unit d a
data UnitInfo (d :: Dimensions) = UnitInfo (UnitValue d) String String -- value, abbreviation, name
type AnyUnitInfo = forall (d :: Dimensions).UnitInfo d
Then you could have a Map Dimension AnyUnitInfo
that listed your preferred units to be displayed for every dimension you feel you are likely to encounter. This would be a powerful tool for formatting your output.
It would add value beyond the current Show instance for dimensional values because it would:
We have discussed whether the Dimensional
constructor should be exposed (see #19). It is occasionally useful, but I think it could be replaced by:
siUnit :: Num a => Unit d a
siUnit = Dimensional 1
Using fmap
as an example:
fmap f x = f (x /~ siUnit) *~ siUnit
See any problems or loopholes with siUnit
?
(siUnit
was siBaseUnit
but that was a misnomer as it may be either a base SI unit or a derived SI unit.)
Have you looked at the intersection between dimensions and randomness? The (strangely named) random-fu
package seems to be popular and reasonably comprehensive.
It would be nice to have a RVar (Length Double)
instead of an RVar Double
that I happen to know is in feet, but for some reason I can't think of the right way to get there from here.
Some desirable things would be:
Dimensional
.I'm a little hazy on how GHC's fixity declaration system works.
Is there any way we can make it so we can write:
1 *~ poundForce / inch ^ pos2
instead of
1 *~ (poundForce / inch ^ pos2)
Or would it make something horrible happen in some other sort expression?
Would they be worth taking a dependency on the exact-pi library (which itself only depends on base)?
This question only really applies to the named-units branch, because it requires all the same machinery for making Unit
a data
type while keeping Quantity
as a newtype
. It arises for the same reason (wanting to add extra runtime information to units).
It's one of the first steps in a long road that leads to useful fixed point quantity types.
I think there is merit to replacing:
data Dimensions = Dim NumType NumType NumType NumType NumType NumType NumType
with:
data Dimension = Dim NumType NumType NumType NumType NumType NumType NumType
This is because an instance of this type represents a dimension. The fact that it is constructed of some other dimensions, usually, unless it is DOne, is operationally important but shouldn't guide the choice of name.
Changing it to the singular would make kind signatures that use it, which will be all over the place in the linear algebra package, easier to understand.
Type families have opened up the possibility of rewriting the Dimension
s using type families. Examples:
type DArea = DLength * DLength
type Area = Quantity DArea
type DVolume = DLength ^ Pos3
type Volume = Quantity DVolume
I feel this could be instructive, but perhaps detrimental to the searchability for suitable Dimension
s, so I'm not sure if it is a good idea or not.
Either way I don't want to make this kind of change at this time as it would severely reduce the portability to/from dimensional-fd. Perhaps when dimensional-fd has been deprecated in favor of dimensional-dk and I stop maintaining it.
It would be great if we could use dimensional values in combination with the Data.Dynamic module.
The problem right now is:
<interactive>:79:1:
No instance for (Typeable 3) arising from a use of `toDyn'
In the expression: toDyn w
In an equation for `it': it = toDyn w
It's related to GHC ticket 8778.
This might be an argument for holding off on the switch to GHC's built-in type-level naturals.
Is there any sense to allowing negative units, e.g. definitions of the following form:
negawatt :: Unit DEnergy
negawatt = prefix (-1) (mega watt)
I don't believe there is. I am contemplating a change that would make it less fully supported, and I'm wondering if perhaps it should be banned outright as unexpected and a potential trap.
AFAICS, the NIST Guide doesn't have anything to say about this. The UCUM disallows it, see http://unitsofmeasure.org/ucum.html#section-Syntax-Rules.
The Show instance for Quantity includes some code which essentially extracts a term-level description of a dimension.
I would like to see this split explicitly into two phases, because I have other planned uses for the term-level description. (For example, it is useful when the dimension parameter of Quantity is existentially qualified, if we are writing code that is working with quantities but doesn't know their dimensions.)
instance ( ToInteger (NT l)
, ToInteger (NT m)
, ToInteger (NT t)
, ToInteger (NT i)
, ToInteger (NT th)
, ToInteger (NT n)
, ToInteger (NT j)
, Show a) =>
Show (Quantity (Dim l m t i th n j) a)
where
show (Dimensional x) = let units = [ dimUnit "m" (undefined :: NT l)
, dimUnit "kg" (undefined :: NT m)
, dimUnit "s" (undefined :: NT t)
, dimUnit "A" (undefined :: NT i)
, dimUnit "K" (undefined :: NT th)
, dimUnit "mol" (undefined :: NT n)
, dimUnit "cd" (undefined :: NT j)
]
in unwords (show x : catMaybes units)
Can we instead have a function whatIsMyName :: forall (d :: Dimension).Proxy d -> Dimensions
? The show function would then convert Dimensions
to [Integer]
in the obvious way, and then to [Maybe String]
?
toSIBasis :: Dimensions -> [Integer]
toSIBasis (Dimensions l m t i th n j) = fmap N.toInteger [l, m, t, i, th, n, j]
It may be the case that Data.Proxy and/or the Sing typeclass in GHC.TypeLits is the correct way to write the function that gets you from a type-level Dimensions to a term-level Dimensions, but it is apparently too late at night for me to figure that out. I think I once knew but I can't dig it up now.
I am making a LaTeX user manual.
Requested content includes:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.