Closed AtelierSnek closed 4 years ago
Hi @AtelierFox, I may be missing your point but for decay
I think you would be better off with the straightforward type:
decay :: Fractional f => s -> Quantity d f -> Quantity d f
You probably also need to be more specific about the type s
. If it is a ratio then Dimensionless f
might be an appropriate substitution. For example:
import Numeric.Units.Dimensional.Prelude
import qualified Prelude
decay :: Floating f => Dimensionless f -> Quantity d f -> Quantity d f
decay t x = x * exp (negate t)
Usage:
>>> decay _1 (1 *~ candela)
0.36787944117144233 cd
>>> decay (0.5 *~ one) (10 *~ weber)
6.065306597126334 m^2 kg s^-2 A^-1
If this is not what you are looking for perhaps could you provide some pseudo-code illustrating what you want to do?
The idea is I want to create a data family such that each instance defines a dimension, and operations upon it (that are true and applicable for all instances). In particular, I'm trying encode various methods of sense. Using the example of human sight, we see things by photons (which would be LuminousIntensity or LuminousFlux), but if we talk about birds, they can also detect magnetic fields (which would be MagneticFlux). I used decay as an example function but it may not be a good one. A better example is
minDetectable :: Fractional f => s -> Quantity b f
where s is the data type of the family, and the function returns the smallest quantity that is detectable by the creature:
class Sense s where
data SenseUnit s :: *
[...]
Does that make more sense?
Maybe I am still not understanding what you are trying to do, but I am not sure you need data families for this, not how they would help. See the below example with (multi-parameter) type classes:
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
import Numeric.Units.Dimensional.Prelude
data Human = KingArthur | SirBelvedere
data Bird = AfricanSwallow
class Sensing species d where
minDetectable :: Fractional a => species -> Quantity d a
instance Sensing Human DLuminousFlux where
minDetectable KingArthur = 1e-2 *~ lumen
minDetectable SirBelvedere = 1e-1 *~ lumen
instance Sensing Bird DLuminousFlux where
minDetectable _ = 1e-3 *~ lumen
instance Sensing Bird DMagneticFlux where
minDetectable _ = 25000 *~ nano tesla * (1 *~ milli meter ^ pos2)
Usage:
>>> minDetectable KingArthur /~ lumen
1.0e-2
>>> minDetectable AfricanSwallow /~ weber
2.5e-11
If I am still missing the point please provide an example (in code or pseudo-code) of how you would use the code you are trying to write!
Oooh, I didn't know about multi-param type classes. That's perfect! That's exactly what I was trying to do.
Say I want to write a function that necessarily takes in a quantity and outputs some other quantity (of the same type), that's easy enough:
decay :: (Fractional f, Quantity b f ~ Quantity c g) => s -> Quantity b f -> Quantity c g
(By the by, am I doing this correctly?)How would I create a type class / type family that specifies or encodes its units? The use case here is I want a type class or type family that is strictly denominated in a particular unit.
The class of all lamps, where all the functions use LuminousFlux is do-able, but what about the super-class of all things that emit a field, that can use one of LuminousFlux or MagneticFlux?
Hope that makes sense