{-# Language TemplateHaskell #-}
-- | Add constraints and a reasonable value to chunks that are quantities.
module Language.Drasil.Chunk.Constrained (
  -- * Constrained Chunks
  -- ** From an Idea
  ConstrainedChunk(..), cuc, cvc, cnstrw,
  -- ** From a Concept
  ConstrConcept(..),
  cnstrw', constrained', constrainedNRV', cuc', cuc'') where

import Control.Lens ((^.), makeLenses, view)

import Language.Drasil.Chunk.Concept (cw, dcc)
import Language.Drasil.Chunk.DefinedQuantity (DefinedQuantityDict, dqd, dqd', dqdWr)
import Language.Drasil.Chunk.Quantity (QuantityDict, qw, vc)
import Language.Drasil.Chunk.Unital (ucs)
import Language.Drasil.Chunk.Unitary (unitary)
import Language.Drasil.Symbol (HasSymbol(..), Symbol)
import Language.Drasil.Classes (NamedIdea(term), Idea(getA), Express(express),
  Definition(defn), ConceptDomain(cdom), Concept, Quantity,
  IsUnit, Constrained(constraints), HasReasVal(reasVal))
import Language.Drasil.Constraint (ConstraintE)
import Language.Drasil.Chunk.UnitDefn (unitWrapper, MayHaveUnit(getUnit))
import Language.Drasil.Expr.Lang (Expr(..))
import Language.Drasil.Expr.Class (sy)
import Language.Drasil.NounPhrase.Core (NP)
import Language.Drasil.Space (Space, HasSpace(..))
import Language.Drasil.Stages (Stage)
import Language.Drasil.UID (HasUID(..))

-- | ConstrainedChunks are symbolic quantities ('QuantityDict')
-- with 'Constraint's and maybe a typical value ('Maybe' 'Expr').
--
-- Ex. Measuring the length of a pendulum would have some reasonable value (between 1 cm and 2 m)
-- and the constraint that the length cannot be a negative value.
data ConstrainedChunk = ConstrainedChunk { ConstrainedChunk -> QuantityDict
_qd     :: QuantityDict
                                         , ConstrainedChunk -> [ConstraintE]
_constr :: [ConstraintE]
                                         , ConstrainedChunk -> Maybe Expr
_reasV  :: Maybe Expr
                                         }
makeLenses ''ConstrainedChunk

-- | Finds 'UID' of the 'QuantityDict' used to make the 'ConstrainedChunk'.
instance HasUID        ConstrainedChunk where uid :: (UID -> f UID) -> ConstrainedChunk -> f ConstrainedChunk
uid = (QuantityDict -> f QuantityDict)
-> ConstrainedChunk -> f ConstrainedChunk
Lens' ConstrainedChunk QuantityDict
qd ((QuantityDict -> f QuantityDict)
 -> ConstrainedChunk -> f ConstrainedChunk)
-> ((UID -> f UID) -> QuantityDict -> f QuantityDict)
-> (UID -> f UID)
-> ConstrainedChunk
-> f ConstrainedChunk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UID -> f UID) -> QuantityDict -> f QuantityDict
forall c. HasUID c => Lens' c UID
uid
-- | Finds term ('NP') of the 'QuantityDict' used to make the 'ConstrainedChunk'.
instance NamedIdea     ConstrainedChunk where term :: (NP -> f NP) -> ConstrainedChunk -> f ConstrainedChunk
term = (QuantityDict -> f QuantityDict)
-> ConstrainedChunk -> f ConstrainedChunk
Lens' ConstrainedChunk QuantityDict
qd ((QuantityDict -> f QuantityDict)
 -> ConstrainedChunk -> f ConstrainedChunk)
-> ((NP -> f NP) -> QuantityDict -> f QuantityDict)
-> (NP -> f NP)
-> ConstrainedChunk
-> f ConstrainedChunk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (NP -> f NP) -> QuantityDict -> f QuantityDict
forall c. NamedIdea c => Lens' c NP
term
-- | Finds the idea contained in the 'QuantityDict' used to make the 'ConstrainedChunk'.
instance Idea          ConstrainedChunk where getA :: ConstrainedChunk -> Maybe String
getA = QuantityDict -> Maybe String
forall c. Idea c => c -> Maybe String
getA (QuantityDict -> Maybe String)
-> (ConstrainedChunk -> QuantityDict)
-> ConstrainedChunk
-> Maybe String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting QuantityDict ConstrainedChunk QuantityDict
-> ConstrainedChunk -> QuantityDict
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting QuantityDict ConstrainedChunk QuantityDict
Lens' ConstrainedChunk QuantityDict
qd
-- | Finds the 'Space' of the 'QuantityDict' used to make the 'ConstrainedChunk'.
instance HasSpace      ConstrainedChunk where typ :: (Space -> f Space) -> ConstrainedChunk -> f ConstrainedChunk
typ = (QuantityDict -> f QuantityDict)
-> ConstrainedChunk -> f ConstrainedChunk
Lens' ConstrainedChunk QuantityDict
qd ((QuantityDict -> f QuantityDict)
 -> ConstrainedChunk -> f ConstrainedChunk)
-> ((Space -> f Space) -> QuantityDict -> f QuantityDict)
-> (Space -> f Space)
-> ConstrainedChunk
-> f ConstrainedChunk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Space -> f Space) -> QuantityDict -> f QuantityDict
forall c. HasSpace c => Lens' c Space
typ
-- | Finds the 'Symbol' of the 'QuantityDict' used to make the 'ConstrainedChunk'.
instance HasSymbol     ConstrainedChunk where symbol :: ConstrainedChunk -> Stage -> Symbol
symbol c :: ConstrainedChunk
c = QuantityDict -> Stage -> Symbol
forall c. HasSymbol c => c -> Stage -> Symbol
symbol (ConstrainedChunk
cConstrainedChunk
-> Getting QuantityDict ConstrainedChunk QuantityDict
-> QuantityDict
forall s a. s -> Getting a s a -> a
^.Getting QuantityDict ConstrainedChunk QuantityDict
Lens' ConstrainedChunk QuantityDict
qd)
-- | 'ConstrainedChunk's have a 'Quantity'. 
instance Quantity      ConstrainedChunk where
-- | Finds the 'Constraint's of a 'ConstrainedChunk'.
instance Constrained   ConstrainedChunk where constraints :: ([ConstraintE] -> f [ConstraintE])
-> ConstrainedChunk -> f ConstrainedChunk
constraints = ([ConstraintE] -> f [ConstraintE])
-> ConstrainedChunk -> f ConstrainedChunk
Lens' ConstrainedChunk [ConstraintE]
constr
-- | Finds a reasonable value for the 'ConstrainedChunk'.
instance HasReasVal    ConstrainedChunk where reasVal :: (Maybe Expr -> f (Maybe Expr))
-> ConstrainedChunk -> f ConstrainedChunk
reasVal     = (Maybe Expr -> f (Maybe Expr))
-> ConstrainedChunk -> f ConstrainedChunk
Lens' ConstrainedChunk (Maybe Expr)
reasV
-- | Equal if 'UID's are equal.
instance Eq            ConstrainedChunk where c1 :: ConstrainedChunk
c1 == :: ConstrainedChunk -> ConstrainedChunk -> Bool
== c2 :: ConstrainedChunk
c2 = (ConstrainedChunk
c1 ConstrainedChunk -> Getting UID ConstrainedChunk UID -> UID
forall s a. s -> Getting a s a -> a
^. (QuantityDict -> Const UID QuantityDict)
-> ConstrainedChunk -> Const UID ConstrainedChunk
Lens' ConstrainedChunk QuantityDict
qd ((QuantityDict -> Const UID QuantityDict)
 -> ConstrainedChunk -> Const UID ConstrainedChunk)
-> ((UID -> Const UID UID)
    -> QuantityDict -> Const UID QuantityDict)
-> Getting UID ConstrainedChunk UID
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UID -> Const UID UID) -> QuantityDict -> Const UID QuantityDict
forall c. HasUID c => Lens' c UID
uid) UID -> UID -> Bool
forall a. Eq a => a -> a -> Bool
== (ConstrainedChunk
c2 ConstrainedChunk -> Getting UID ConstrainedChunk UID -> UID
forall s a. s -> Getting a s a -> a
^. (QuantityDict -> Const UID QuantityDict)
-> ConstrainedChunk -> Const UID ConstrainedChunk
Lens' ConstrainedChunk QuantityDict
qd ((QuantityDict -> Const UID QuantityDict)
 -> ConstrainedChunk -> Const UID ConstrainedChunk)
-> ((UID -> Const UID UID)
    -> QuantityDict -> Const UID QuantityDict)
-> Getting UID ConstrainedChunk UID
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UID -> Const UID UID) -> QuantityDict -> Const UID QuantityDict
forall c. HasUID c => Lens' c UID
uid)
-- | Finds units contained in the 'QuantityDict' used to make the 'ConstrainedChunk'.
instance MayHaveUnit   ConstrainedChunk where getUnit :: ConstrainedChunk -> Maybe UnitDefn
getUnit = QuantityDict -> Maybe UnitDefn
forall u. MayHaveUnit u => u -> Maybe UnitDefn
getUnit (QuantityDict -> Maybe UnitDefn)
-> (ConstrainedChunk -> QuantityDict)
-> ConstrainedChunk
-> Maybe UnitDefn
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting QuantityDict ConstrainedChunk QuantityDict
-> ConstrainedChunk -> QuantityDict
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting QuantityDict ConstrainedChunk QuantityDict
Lens' ConstrainedChunk QuantityDict
qd

-- | Creates a constrained unitary chunk from a 'UID', term ('NP'), 'Symbol', unit, 'Space', 'Constraint's, and an 'Expr'.
cuc :: (IsUnit u) => String -> NP -> Symbol -> u
  -> Space -> [ConstraintE] -> Expr -> ConstrainedChunk
cuc :: String
-> NP
-> Symbol
-> u
-> Space
-> [ConstraintE]
-> Expr
-> ConstrainedChunk
cuc i :: String
i t :: NP
t s :: Symbol
s u :: u
u space :: Space
space cs :: [ConstraintE]
cs rv :: Expr
rv = QuantityDict -> [ConstraintE] -> Maybe Expr -> ConstrainedChunk
ConstrainedChunk (UnitaryChunk -> QuantityDict
forall q. (Quantity q, MayHaveUnit q) => q -> QuantityDict
qw (String -> NP -> Symbol -> u -> Space -> UnitaryChunk
forall u.
IsUnit u =>
String -> NP -> Symbol -> u -> Space -> UnitaryChunk
unitary String
i NP
t Symbol
s u
u Space
space)) [ConstraintE]
cs (Expr -> Maybe Expr
forall a. a -> Maybe a
Just Expr
rv)

-- | Creates a constrained unitary chunk from a 'UID', term ('NP'), 'Symbol', 'Space', 'Constraint's, and a 'Maybe' 'Expr' (Similar to 'cuc' but no units).
cvc :: String -> NP -> Symbol -> Space -> [ConstraintE] -> Maybe Expr -> ConstrainedChunk
cvc :: String
-> NP
-> Symbol
-> Space
-> [ConstraintE]
-> Maybe Expr
-> ConstrainedChunk
cvc i :: String
i des :: NP
des sym :: Symbol
sym space :: Space
space = QuantityDict -> [ConstraintE] -> Maybe Expr -> ConstrainedChunk
ConstrainedChunk (QuantityDict -> QuantityDict
forall q. (Quantity q, MayHaveUnit q) => q -> QuantityDict
qw (String -> NP -> Symbol -> Space -> QuantityDict
vc String
i NP
des Symbol
sym Space
space))

-- | Creates a new ConstrainedChunk from either a 'ConstrainedChunk', 'ConstrConcept', 'UncertainChunk', or an 'UncertQ'.
cnstrw :: (Quantity c, Constrained c, HasReasVal c, MayHaveUnit c) => c -> ConstrainedChunk
cnstrw :: c -> ConstrainedChunk
cnstrw c :: c
c = QuantityDict -> [ConstraintE] -> Maybe Expr -> ConstrainedChunk
ConstrainedChunk (c -> QuantityDict
forall q. (Quantity q, MayHaveUnit q) => q -> QuantityDict
qw c
c) (c
c c -> Getting [ConstraintE] c [ConstraintE] -> [ConstraintE]
forall s a. s -> Getting a s a -> a
^. Getting [ConstraintE] c [ConstraintE]
forall c. Constrained c => Lens' c [ConstraintE]
constraints) (c
c c -> Getting (Maybe Expr) c (Maybe Expr) -> Maybe Expr
forall s a. s -> Getting a s a -> a
^. Getting (Maybe Expr) c (Maybe Expr)
forall c. HasReasVal c => Lens' c (Maybe Expr)
reasVal)

-- | ConstrConcepts are conceptual symbolic quantities ('DefinedQuantityDict')
-- with 'Constraint's and maybe a reasonable value (no units!).
-- Similar to 'ConstrainedChunk' but includes a definition and domain. 
--
-- Ex. Measuring the length of a pendulum arm could be a concept that has some reasonable value
-- (between 1 cm and 2 m) and the constraint that the length cannot be a negative value.
data ConstrConcept = ConstrConcept { ConstrConcept -> DefinedQuantityDict
_defq    :: DefinedQuantityDict
                                   , ConstrConcept -> [ConstraintE]
_constr' :: [ConstraintE]
                                   , ConstrConcept -> Maybe Expr
_reasV'  :: Maybe Expr
                                   }
makeLenses ''ConstrConcept

-- | Finds 'UID' of the 'DefinedQuantityDict' used to make the 'ConstrConcept'.
instance HasUID        ConstrConcept where uid :: (UID -> f UID) -> ConstrConcept -> f ConstrConcept
uid = (DefinedQuantityDict -> f DefinedQuantityDict)
-> ConstrConcept -> f ConstrConcept
Lens' ConstrConcept DefinedQuantityDict
defq ((DefinedQuantityDict -> f DefinedQuantityDict)
 -> ConstrConcept -> f ConstrConcept)
-> ((UID -> f UID) -> DefinedQuantityDict -> f DefinedQuantityDict)
-> (UID -> f UID)
-> ConstrConcept
-> f ConstrConcept
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UID -> f UID) -> DefinedQuantityDict -> f DefinedQuantityDict
forall c. HasUID c => Lens' c UID
uid
-- | Finds term ('NP') of the 'DefinedQuantityDict' used to make the 'ConstrConcept'.
instance NamedIdea     ConstrConcept where term :: (NP -> f NP) -> ConstrConcept -> f ConstrConcept
term = (DefinedQuantityDict -> f DefinedQuantityDict)
-> ConstrConcept -> f ConstrConcept
Lens' ConstrConcept DefinedQuantityDict
defq ((DefinedQuantityDict -> f DefinedQuantityDict)
 -> ConstrConcept -> f ConstrConcept)
-> ((NP -> f NP) -> DefinedQuantityDict -> f DefinedQuantityDict)
-> (NP -> f NP)
-> ConstrConcept
-> f ConstrConcept
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (NP -> f NP) -> DefinedQuantityDict -> f DefinedQuantityDict
forall c. NamedIdea c => Lens' c NP
term
-- | Finds the idea contained in the 'DefinedQuantityDict' used to make the 'ConstrConcept'.
instance Idea          ConstrConcept where getA :: ConstrConcept -> Maybe String
getA = DefinedQuantityDict -> Maybe String
forall c. Idea c => c -> Maybe String
getA (DefinedQuantityDict -> Maybe String)
-> (ConstrConcept -> DefinedQuantityDict)
-> ConstrConcept
-> Maybe String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting DefinedQuantityDict ConstrConcept DefinedQuantityDict
-> ConstrConcept -> DefinedQuantityDict
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting DefinedQuantityDict ConstrConcept DefinedQuantityDict
Lens' ConstrConcept DefinedQuantityDict
defq
-- | Finds the 'Space' of the 'DefinedQuantityDict' used to make the 'ConstrConcept'.
instance HasSpace      ConstrConcept where typ :: (Space -> f Space) -> ConstrConcept -> f ConstrConcept
typ = (DefinedQuantityDict -> f DefinedQuantityDict)
-> ConstrConcept -> f ConstrConcept
Lens' ConstrConcept DefinedQuantityDict
defq ((DefinedQuantityDict -> f DefinedQuantityDict)
 -> ConstrConcept -> f ConstrConcept)
-> ((Space -> f Space)
    -> DefinedQuantityDict -> f DefinedQuantityDict)
-> (Space -> f Space)
-> ConstrConcept
-> f ConstrConcept
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Space -> f Space) -> DefinedQuantityDict -> f DefinedQuantityDict
forall c. HasSpace c => Lens' c Space
typ
-- | Finds the 'Symbol' of the 'DefinedQuantityDict' used to make the 'ConstrConcept'.
instance HasSymbol     ConstrConcept where symbol :: ConstrConcept -> Stage -> Symbol
symbol c :: ConstrConcept
c = DefinedQuantityDict -> Stage -> Symbol
forall c. HasSymbol c => c -> Stage -> Symbol
symbol (ConstrConcept
cConstrConcept
-> Getting DefinedQuantityDict ConstrConcept DefinedQuantityDict
-> DefinedQuantityDict
forall s a. s -> Getting a s a -> a
^.Getting DefinedQuantityDict ConstrConcept DefinedQuantityDict
Lens' ConstrConcept DefinedQuantityDict
defq)
-- | 'ConstrConcept's have a 'Quantity'. 
instance Quantity      ConstrConcept where
-- | Finds definition of the 'DefinedQuantityDict' used to make the 'ConstrConcept'.
instance Definition    ConstrConcept where defn :: (Sentence -> f Sentence) -> ConstrConcept -> f ConstrConcept
defn = (DefinedQuantityDict -> f DefinedQuantityDict)
-> ConstrConcept -> f ConstrConcept
Lens' ConstrConcept DefinedQuantityDict
defq ((DefinedQuantityDict -> f DefinedQuantityDict)
 -> ConstrConcept -> f ConstrConcept)
-> ((Sentence -> f Sentence)
    -> DefinedQuantityDict -> f DefinedQuantityDict)
-> (Sentence -> f Sentence)
-> ConstrConcept
-> f ConstrConcept
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Sentence -> f Sentence)
-> DefinedQuantityDict -> f DefinedQuantityDict
forall c. Definition c => Lens' c Sentence
defn
-- | Finds the domain contained in the 'DefinedQuantityDict' used to make the 'ConstrConcept'.
instance ConceptDomain ConstrConcept where cdom :: ConstrConcept -> [UID]
cdom = DefinedQuantityDict -> [UID]
forall c. ConceptDomain c => c -> [UID]
cdom (DefinedQuantityDict -> [UID])
-> (ConstrConcept -> DefinedQuantityDict) -> ConstrConcept -> [UID]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting DefinedQuantityDict ConstrConcept DefinedQuantityDict
-> ConstrConcept -> DefinedQuantityDict
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting DefinedQuantityDict ConstrConcept DefinedQuantityDict
Lens' ConstrConcept DefinedQuantityDict
defq
-- | Finds the 'Constraint's of a 'ConstrConcept'.
instance Constrained   ConstrConcept where constraints :: ([ConstraintE] -> f [ConstraintE])
-> ConstrConcept -> f ConstrConcept
constraints  = ([ConstraintE] -> f [ConstraintE])
-> ConstrConcept -> f ConstrConcept
Lens' ConstrConcept [ConstraintE]
constr'
-- | Finds a reasonable value for the 'ConstrConcept'.
instance HasReasVal    ConstrConcept where reasVal :: (Maybe Expr -> f (Maybe Expr)) -> ConstrConcept -> f ConstrConcept
reasVal      = (Maybe Expr -> f (Maybe Expr)) -> ConstrConcept -> f ConstrConcept
Lens' ConstrConcept (Maybe Expr)
reasV'
-- | Equal if 'UID's are equal.
instance Eq            ConstrConcept where c1 :: ConstrConcept
c1 == :: ConstrConcept -> ConstrConcept -> Bool
== c2 :: ConstrConcept
c2 = (ConstrConcept
c1 ConstrConcept -> Getting UID ConstrConcept UID -> UID
forall s a. s -> Getting a s a -> a
^.(DefinedQuantityDict -> Const UID DefinedQuantityDict)
-> ConstrConcept -> Const UID ConstrConcept
Lens' ConstrConcept DefinedQuantityDict
defq((DefinedQuantityDict -> Const UID DefinedQuantityDict)
 -> ConstrConcept -> Const UID ConstrConcept)
-> ((UID -> Const UID UID)
    -> DefinedQuantityDict -> Const UID DefinedQuantityDict)
-> Getting UID ConstrConcept UID
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(UID -> Const UID UID)
-> DefinedQuantityDict -> Const UID DefinedQuantityDict
forall c. HasUID c => Lens' c UID
uid) UID -> UID -> Bool
forall a. Eq a => a -> a -> Bool
== (ConstrConcept
c2 ConstrConcept -> Getting UID ConstrConcept UID -> UID
forall s a. s -> Getting a s a -> a
^.(DefinedQuantityDict -> Const UID DefinedQuantityDict)
-> ConstrConcept -> Const UID ConstrConcept
Lens' ConstrConcept DefinedQuantityDict
defq((DefinedQuantityDict -> Const UID DefinedQuantityDict)
 -> ConstrConcept -> Const UID ConstrConcept)
-> ((UID -> Const UID UID)
    -> DefinedQuantityDict -> Const UID DefinedQuantityDict)
-> Getting UID ConstrConcept UID
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(UID -> Const UID UID)
-> DefinedQuantityDict -> Const UID DefinedQuantityDict
forall c. HasUID c => Lens' c UID
uid)
-- | Finds the units of the 'DefinedQuantityDict' used to make the 'ConstrConcept'.
instance MayHaveUnit   ConstrConcept where getUnit :: ConstrConcept -> Maybe UnitDefn
getUnit = DefinedQuantityDict -> Maybe UnitDefn
forall u. MayHaveUnit u => u -> Maybe UnitDefn
getUnit (DefinedQuantityDict -> Maybe UnitDefn)
-> (ConstrConcept -> DefinedQuantityDict)
-> ConstrConcept
-> Maybe UnitDefn
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting DefinedQuantityDict ConstrConcept DefinedQuantityDict
-> ConstrConcept -> DefinedQuantityDict
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting DefinedQuantityDict ConstrConcept DefinedQuantityDict
Lens' ConstrConcept DefinedQuantityDict
defq
-- | Convert the symbol of the 'ConstrConcept' to a 'ModelExpr'.
instance Express       ConstrConcept where express :: ConstrConcept -> ModelExpr
express = ConstrConcept -> ModelExpr
forall r c. (ExprC r, HasUID c, HasSymbol c) => c -> r
sy

-- | Creates a 'ConstrConcept' with a quantitative concept, a list of 'Constraint's and an 'Expr'.
constrained' :: (Concept c, MayHaveUnit c, Quantity c) =>
  c -> [ConstraintE] -> Expr -> ConstrConcept
constrained' :: c -> [ConstraintE] -> Expr -> ConstrConcept
constrained' q :: c
q cs :: [ConstraintE]
cs rv :: Expr
rv = DefinedQuantityDict -> [ConstraintE] -> Maybe Expr -> ConstrConcept
ConstrConcept (c -> DefinedQuantityDict
forall c.
(Quantity c, Concept c, MayHaveUnit c) =>
c -> DefinedQuantityDict
dqdWr c
q) [ConstraintE]
cs (Expr -> Maybe Expr
forall a. a -> Maybe a
Just Expr
rv)

-- | Similar to 'constrained'', but defaults 'Maybe' 'Expr' to 'Nothing'.
constrainedNRV' :: (Concept c, MayHaveUnit c, Quantity c) =>
  c -> [ConstraintE] -> ConstrConcept
constrainedNRV' :: c -> [ConstraintE] -> ConstrConcept
constrainedNRV' q :: c
q cs :: [ConstraintE]
cs = DefinedQuantityDict -> [ConstraintE] -> Maybe Expr -> ConstrConcept
ConstrConcept (c -> DefinedQuantityDict
forall c.
(Quantity c, Concept c, MayHaveUnit c) =>
c -> DefinedQuantityDict
dqdWr c
q) [ConstraintE]
cs Maybe Expr
forall a. Maybe a
Nothing

-- | Creates a constrained unitary chunk from a 'UID', term ('NP'), description ('String'), 'Symbol', unit, 'Space', 'Constraint's, and an 'Expr'.
cuc' :: (IsUnit u) => String -> NP -> String -> Symbol -> u
            -> Space -> [ConstraintE] -> Expr -> ConstrConcept
cuc' :: String
-> NP
-> String
-> Symbol
-> u
-> Space
-> [ConstraintE]
-> Expr
-> ConstrConcept
cuc' nam :: String
nam trm :: NP
trm desc :: String
desc sym :: Symbol
sym un :: u
un space :: Space
space cs :: [ConstraintE]
cs rv :: Expr
rv =
  DefinedQuantityDict -> [ConstraintE] -> Maybe Expr -> ConstrConcept
ConstrConcept (ConceptChunk -> Symbol -> Space -> UnitDefn -> DefinedQuantityDict
forall u.
IsUnit u =>
ConceptChunk -> Symbol -> Space -> u -> DefinedQuantityDict
dqd (UnitalChunk -> ConceptChunk
forall c. Concept c => c -> ConceptChunk
cw (String -> NP -> String -> Symbol -> Space -> u -> UnitalChunk
forall u.
IsUnit u =>
String -> NP -> String -> Symbol -> Space -> u -> UnitalChunk
ucs String
nam NP
trm String
desc Symbol
sym Space
space u
un)) Symbol
sym Space
space UnitDefn
uu) [ConstraintE]
cs (Expr -> Maybe Expr
forall a. a -> Maybe a
Just Expr
rv)
  where uu :: UnitDefn
uu = u -> UnitDefn
forall u. IsUnit u => u -> UnitDefn
unitWrapper u
un

-- | Similar to 'cuc'', but 'Symbol' is dependent on 'Stage'.
cuc'' :: (IsUnit u) => String -> NP -> String -> (Stage -> Symbol) -> u
            -> Space -> [ConstraintE] -> Expr -> ConstrConcept
cuc'' :: String
-> NP
-> String
-> (Stage -> Symbol)
-> u
-> Space
-> [ConstraintE]
-> Expr
-> ConstrConcept
cuc'' nam :: String
nam trm :: NP
trm desc :: String
desc sym :: Stage -> Symbol
sym un :: u
un space :: Space
space cs :: [ConstraintE]
cs rv :: Expr
rv =
  DefinedQuantityDict -> [ConstraintE] -> Maybe Expr -> ConstrConcept
ConstrConcept (ConceptChunk
-> (Stage -> Symbol)
-> Space
-> Maybe UnitDefn
-> DefinedQuantityDict
dqd' (String -> NP -> String -> ConceptChunk
dcc String
nam NP
trm String
desc) Stage -> Symbol
sym Space
space (UnitDefn -> Maybe UnitDefn
forall a. a -> Maybe a
Just UnitDefn
uu)) [ConstraintE]
cs (Expr -> Maybe Expr
forall a. a -> Maybe a
Just Expr
rv)
  where uu :: UnitDefn
uu = u -> UnitDefn
forall u. IsUnit u => u -> UnitDefn
unitWrapper u
un

-- | Similar to 'cnstrw', but types must also have a 'Concept'.
cnstrw' :: (Quantity c, Concept c, Constrained c, HasReasVal c, MayHaveUnit c) => c -> ConstrConcept
cnstrw' :: c -> ConstrConcept
cnstrw' c :: c
c = DefinedQuantityDict -> [ConstraintE] -> Maybe Expr -> ConstrConcept
ConstrConcept (c -> DefinedQuantityDict
forall c.
(Quantity c, Concept c, MayHaveUnit c) =>
c -> DefinedQuantityDict
dqdWr c
c) (c
c c -> Getting [ConstraintE] c [ConstraintE] -> [ConstraintE]
forall s a. s -> Getting a s a -> a
^. Getting [ConstraintE] c [ConstraintE]
forall c. Constrained c => Lens' c [ConstraintE]
constraints) (c
c c -> Getting (Maybe Expr) c (Maybe Expr) -> Maybe Expr
forall s a. s -> Getting a s a -> a
^. Getting (Maybe Expr) c (Maybe Expr)
forall c. HasReasVal c => Lens' c (Maybe Expr)
reasVal)