uom-plugin icon indicating copy to clipboard operation
uom-plugin copied to clipboard

Haskell expressions as conversion factors

Open expipiplus1 opened this issue 10 years ago • 3 comments

How realistic is this?

It would be nice to be able to define degrees as [u| deg = (pi / 180) rad |] and have that expression spliced into convert.

This would be particularly useful for my exact real package, where any constant ratio may not be precise enough.

expipiplus1 avatar Nov 25 '15 23:11 expipiplus1

There are two separate issues here.

The Template Haskell quasiquoter would need to parse and splice arbitrary Haskell expressions, which in principle is possible, but would require quite a bit of work. In the short term you can always expand the TH manually, which in this case would be something like

-- [u| rad |]
type instance MkUnit "rad" = Base "rad"
instance HasCanonicalBaseUnit "rad"

-- [u| deg = (pi / 180) rad |]
type instance MkUnit "deg" = Base "deg"
instance HasCanonicalBaseUnit "deg" where
  type CanonicalBaseUnit "deg" = "rad"
  conversionBase _ = (pi / 180) *: [u| 1 deg/rad |]

Unfortunately there is a bigger problem, which is that at the moment conversionBase is required to be Rational rather than an arbitrary numeric type. It might be possible to generalise this and keep convert, I forget the details...

adamgundry avatar Nov 27 '15 21:11 adamgundry

It's probably a niche request. I'd be happy to look into generalizing conversionBase myself.

expipiplus1 avatar Nov 28 '15 19:11 expipiplus1

I need to convert between units of degrees and radians too. When radians are defined "to require explicit conversion", as they are in the Defs module with [u| rad 1 1 |], equivalent to declareConvertibleUnit "rad" 1 "1", I haven't found a way for degrees to be setup as a conversion from radians without getting an error ...

declareConvertibleUnit "rad" 1 "1"
declareConvertibleUnit "deg" (5030569068109113 % 288230376151711744) "rad"

Couldn't match type ‘One’ with ‘Base "rad"’
In the instance declaration for ‘HasCanonicalBaseUnit "deg"’

Dumping the template splices to show the equivalence of the two forms ...

[u| rad = 1 1 |]
stack build --ghc-options='-ddump-splices -ddump-to-file'
" rad = 1 1 "
======>
type instance MkUnit "rad" = Base "rad",
instance HasCanonicalBaseUnit "rad" where
  type CanonicalBaseUnit "rad" = One
  conversionBase _ = Data.UnitsOfMeasure.Internal.MkQuantity 1.0
declareConvertibleUnit "rad" 1 "1"
stack build --ghc-options='-ddump-splices -ddump-to-file'
declareConvertibleUnit "rad" 1 "1"
======>
type instance MkUnit "rad" = Base "rad"
instance HasCanonicalBaseUnit "rad" where
  type CanonicalBaseUnit "rad" = One
  conversionBase _ = Data.UnitsOfMeasure.Internal.MkQuantity 1.0

I could setup degrees like this as a dimensionless scaling not based on radians ...

[u| deg = (5030569068109113 % 288230376151711744) 1 |]

Here's my working.

philderbeast avatar Jul 24 '17 19:07 philderbeast