{-# Language TemplateHaskell #-}
module Language.Drasil.Uncertainty (
Uncertainty,
HasUncertainty(..),
uncert, prec,
uncty, exact,
defaultUncrt,
uncVal, uncPrec,
) where
import Control.Lens (Lens', (^.), makeLenses)
import Data.Maybe (fromMaybe)
data Uncertainty = Uncert {
Uncertainty -> Maybe Double
_uncert :: Maybe Double,
Uncertainty -> Maybe Int
_prec :: Maybe Int
}
makeLenses ''Uncertainty
class HasUncertainty c where
unc :: Lens' c Uncertainty
uncty :: Double -> Maybe Int -> Uncertainty
uncty :: Double -> Maybe Int -> Uncertainty
uncty Double
u = Maybe Double -> Maybe Int -> Uncertainty
Uncert (Double -> Maybe Double
forall a. a -> Maybe a
Just (Double -> Maybe Double) -> Double -> Maybe Double
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. (Num a, Ord a) => a -> a
isDecimal Double
u)
exact :: Uncertainty
exact :: Uncertainty
exact = Maybe Double -> Maybe Int -> Uncertainty
Uncert Maybe Double
forall a. Maybe a
Nothing Maybe Int
forall a. Maybe a
Nothing
isDecimal :: (Num a, Ord a) => a -> a
isDecimal :: forall a. (Num a, Ord a) => a -> a
isDecimal a
0 = [Char] -> a
forall a. HasCallStack => [Char] -> a
error [Char]
"An uncertain quantity cannot be exact (have 0% uncertainty). Reconsider whether your value is exact or uncertain"
isDecimal a
u = if (a
0 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
u) Bool -> Bool -> Bool
&& (a
u a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
1) then a
u
else [Char] -> a
forall a. HasCallStack => [Char] -> a
error [Char]
"Uncertainty must be between 0 and 1"
defaultUncrt :: Uncertainty
defaultUncrt :: Uncertainty
defaultUncrt = Double -> Maybe Int -> Uncertainty
uncty Double
0.1 (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
0)
uncVal :: HasUncertainty x => x -> Double
uncVal :: forall x. HasUncertainty x => x -> Double
uncVal x
u = Double -> Maybe Double -> Double
forall a. a -> Maybe a -> a
fromMaybe Double
0.0 (Maybe Double -> Double) -> Maybe Double -> Double
forall a b. (a -> b) -> a -> b
$ x
u x -> Getting (Maybe Double) x (Maybe Double) -> Maybe Double
forall s a. s -> Getting a s a -> a
^. ((Uncertainty -> Const (Maybe Double) Uncertainty)
-> x -> Const (Maybe Double) x
forall c. HasUncertainty c => Lens' c Uncertainty
Lens' x Uncertainty
unc ((Uncertainty -> Const (Maybe Double) Uncertainty)
-> x -> Const (Maybe Double) x)
-> ((Maybe Double -> Const (Maybe Double) (Maybe Double))
-> Uncertainty -> Const (Maybe Double) Uncertainty)
-> Getting (Maybe Double) x (Maybe Double)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe Double -> Const (Maybe Double) (Maybe Double))
-> Uncertainty -> Const (Maybe Double) Uncertainty
Lens' Uncertainty (Maybe Double)
uncert)
uncPrec :: HasUncertainty x => x -> Maybe Int
uncPrec :: forall x. HasUncertainty x => x -> Maybe Int
uncPrec x
u = x
u x -> Getting (Maybe Int) x (Maybe Int) -> Maybe Int
forall s a. s -> Getting a s a -> a
^. ((Uncertainty -> Const (Maybe Int) Uncertainty)
-> x -> Const (Maybe Int) x
forall c. HasUncertainty c => Lens' c Uncertainty
Lens' x Uncertainty
unc ((Uncertainty -> Const (Maybe Int) Uncertainty)
-> x -> Const (Maybe Int) x)
-> ((Maybe Int -> Const (Maybe Int) (Maybe Int))
-> Uncertainty -> Const (Maybe Int) Uncertainty)
-> Getting (Maybe Int) x (Maybe Int)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe Int -> Const (Maybe Int) (Maybe Int))
-> Uncertainty -> Const (Maybe Int) Uncertainty
Lens' Uncertainty (Maybe Int)
prec)