-- | Defines the common constructors used to build quantities. module Data.Quantities.Constructors where import Data.Quantities.Data import Data.Quantities.DefaultUnits (defaultDefString) import Data.Quantities.Definitions (readDefinitions) import Data.Quantities.ExprParser (parseExprQuant) -- | Default set of definitions that come predefined. defaultDefinitions :: Either (QuantityError Double) Definitions defaultDefinitions = readDefinitions defaultDefString -- $setup -- >>> import Data.Quantities -- | Create a Quantity by parsing a string. Uses an 'UndefinedUnitError' for -- undefined units. Handles arithmetic expressions as well. -- -- >>> fromString "25 m/s" -- Right 25.0 meter / second -- >>> fromString "fakeunit" -- Left (UndefinedUnitError "fakeunit") -- >>> fromString "ft + 12in" -- Right 2.0 foot -- -- This function also supports unit conversions, by placing \"=>\" in between -- two valid expressions. This behavior is undefined (and returns a -- 'ScalingFactorError') if the quantity to be converted to has a magnitude. -- -- >>> fromString "min => s" -- Right 60.0 second -- >>> fromString "2 ft + 6 in => ft" -- Right 2.5 foot -- >>> fromString "m => 3 ft" -- Left (ScalingFactorError 3.0 foot) -- -- Make sure not to use dimensional quantities in exponents. -- -- >>> fromString "m ** 2" -- Right 1.0 meter ** 2 -- >>> fromString "m ** (2s)" -- Left (ParserError "Used non-dimensionless exponent in ( Right 1.0 meter ) ** ( Right 2.0 second )") fromString :: String -> Either (QuantityError Double) (Quantity Double) fromString s = case defaultDefinitions of (Right d) -> parseExprQuant d s (Left d) -> Left d -- | Create quantities with custom definitions. -- -- >>> let myDefString = defaultDefString ++ "\nmy_unit = 100 s" -- >>> let (Right d) = readDefinitions myDefString -- >>> let myFromString = fromString' d -- >>> myFromString "25 my_unit" -- Right 25.0 my_unit fromString' :: Definitions -> String -> Either (QuantityError Double) (Quantity Double) fromString' = parseExprQuant -- | Parse units from a string. Equivalent to @fmap units . fromString@ -- -- >>> unitsFromString "N * s" -- Right newton second unitsFromString :: String -> Either (QuantityError Double) CompoundUnit unitsFromString = fmap units . fromString