This package should look like Unitful.jl but behave like DynamicQuantities.jl under the hood

Tasks:
1. Consider renaming this to FlexUnits.jl (the flexible unit package)
    Flexible dimensions, units, and registries
2. Migrate to TankMonitor module and run
3. Publish version v0.0.1
4. Register package (including branch protection etc)
5. Fix vague convert info 
    @test convert(Quantity{Float64, AffineUnits}, ubase(1u"kg")) isa Quantity{Float64, AffineUnits{DEFAULT_DIM_TYPE}}
    @test convert(Quantity{Float64, AffineUnits{DEFAULT_DIM_TYPE}}, 1u"kg") isa Quantity{Float64, AffineUnits{DEFAULT_DIM_TYPE}}
    @test convert(Quantity{Float64, Dimensions}, u"kg") isa Quantity{Float64, Dimensions{FAST_RATIONAL}}
    Make it work like:
        S = Diagonal(rand(5))
        convert(Array{<:Any,2}, S)     =>    Matrix{Float64}
        see https://github.com/JuliaLang/julia/blob/056891701e8ec629834def549f565cf80c46ccf9/base/array.jl#L614
6. Add "unit_info(u::Union{Dimension, AbstractUnit{Dimension}})" 
    - Maps dimensions to a meaning (like Force or Inductance) and lists other units of that dimension
    - This can be done without documentation 
        - Use Dict{Dimension,String} to find dimension "meaning" (determine this by unique dimensions)
        - Iterate over registry and list other units that match the query dimension
7. Consier supporting ArrayQuantity (can use some Quantity methods as fallbacks)


Design Decisions:
1.  Unit outputs should be clean and parsable (dimensions don't have to be but should be convertable)
2.  All quantity operations (even affine units) eagerly convert to base dimensional units 
        Displaying quantities with units not having symbol will convert to SI to emphasize this fact
3.  Registry is a module containing a single dict for a registry (AffineUnits because they are the most general)
        Users can easily create their own registries with the RegistryTools module that exports everythign you need
4.  String macros ({x}"...") and parse macros ({x}parse("...")) need the following versions:
        q: produce a Quantity{Float64, Dimensions} (si quantity representation, scale-restrictive)
        us: produce a ScalarUnits{Dimensions} (scaled unit representation, scale-restrictive)
        u: produce an AffineUnits{Dimensions} (affine unit represntation, general)
5.  Macros and parsers ARE NOT EXPORTED BY DEFAULT
        Instead, use "using Dimensionful.Registry" to export them manually
        This prevents polluting namespaces, and allows users to export macros from their own registries
6.  "u" and "us" variants assign the expression as their symbol

7.  You can feed a dictionary to {x}parse(str, dict), to use custom unit registries
        The dict will have have elements of AffineUnits{D} where D is a dimension object
        Build an {x}expression(str, dict) as well for easily building string macros

import DynamicQuantities
import Unitful
using BenchmarkTools

v1flex = ubase.([1u"m/s", 1u"J/kg", 1u"A/V"])
v1uni  = [1*Unitful.u"m/s", 1*Unitful.u"J/kg", 1*Unitful.u"A/V"]
v1dyn  = [1*DynamicQuantities.u"m/s", 1*DynamicQuantities.u"J/kg", 1*DynamicQuantities.u"A/V"]

@btime sum(x->x^0.0, v1uni)
@btime sum(x->x^0.0, v1flex)
@btime sum(x->x^0.0, v1dyn)

t1flex = ubase.((1u"m/s", 1u"J/kg", 1u"A/V"))
t1uni  = (1*Unitful.u"m/s", 1*Unitful.u"J/kg", 1*Unitful.u"A/V")
t1dyn  = (1*DynamicQuantities.u"m/s", 1*DynamicQuantities.u"J/kg", 1*DynamicQuantities.u"A/V")

@btime sum(x->x^0, t1uni)
@btime sum(x->x^0, t1flex)
@btime sum(x->x^0, t1dyn)

Considerations:
N.  Consider commutative macro for promote_rule to prevent repetition
        https://discourse.julialang.org/t/techniques-for-defining-commutative-functions/113406/5
