{-# LANGUAGE RankNTypes, FlexibleInstances, GADTs #-}
{-# OPTIONS_GHC -Wno-redundant-constraints #-}

-- | Contains chunks related to adding an expression to a quantitative concept. 
module Language.Drasil.Chunk.Eq (
  -- * Types
  QDefinition,
  -- * Constructors
  fromEqn, fromEqn', fromEqnSt,
  fromEqnSt', fromEqnSt'', mkQDefSt, mkQuantDef, mkQuantDef', ec,
  mkFuncDef, mkFuncDef', mkFuncDefByQ
) where

import Control.Lens ((^.), view, lens, Lens')
import Language.Drasil.Chunk.UnitDefn (unitWrapper, MayHaveUnit(getUnit), UnitDefn)

import Language.Drasil.Symbol (HasSymbol(symbol), Symbol)
import Language.Drasil.Classes (NamedIdea(term), Idea(getA),
  IsUnit, DefiningExpr(defnExpr), Definition(defn), Quantity,
  ConceptDomain(cdom), Express(express))
import Language.Drasil.Chunk.DefinedQuantity (DefinedQuantityDict, dqd, dqd')
import Language.Drasil.Chunk.Concept (cc')
import Language.Drasil.Chunk.NamedIdea (ncUID, mkIdea, nw)

import Language.Drasil.Expr.Class (ExprC(apply, sy))
import Language.Drasil.ModelExpr.Class (ModelExprC(defines))
import Language.Drasil.ModelExpr.Lang (ModelExpr(C))
import Language.Drasil.NounPhrase.Core (NP)
import Language.Drasil.Space (mkFunction, Space, Space, HasSpace(..))
import Language.Drasil.Sentence (Sentence(EmptyS))
import Language.Drasil.Stages (Stage)
import Language.Drasil.UID (UID, HasUID(..))

data QDefinition e where
  QD :: DefinedQuantityDict -> [UID] -> e -> QDefinition e

qdQua :: Lens' (QDefinition e) DefinedQuantityDict
qdQua :: (DefinedQuantityDict -> f DefinedQuantityDict)
-> QDefinition e -> f (QDefinition e)
qdQua = (QDefinition e -> DefinedQuantityDict)
-> (QDefinition e -> DefinedQuantityDict -> QDefinition e)
-> Lens
     (QDefinition e)
     (QDefinition e)
     DefinedQuantityDict
     DefinedQuantityDict
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens (\(QD qua :: DefinedQuantityDict
qua _ _) -> DefinedQuantityDict
qua) (\(QD _ ins :: [UID]
ins e :: e
e) qua' :: DefinedQuantityDict
qua' -> DefinedQuantityDict -> [UID] -> e -> QDefinition e
forall e. DefinedQuantityDict -> [UID] -> e -> QDefinition e
QD DefinedQuantityDict
qua' [UID]
ins e
e)

qdInputs :: Lens' (QDefinition e) [UID]
qdInputs :: ([UID] -> f [UID]) -> QDefinition e -> f (QDefinition e)
qdInputs = (QDefinition e -> [UID])
-> (QDefinition e -> [UID] -> QDefinition e)
-> Lens (QDefinition e) (QDefinition e) [UID] [UID]
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens (\(QD _ ins :: [UID]
ins _) -> [UID]
ins) (\(QD qua :: DefinedQuantityDict
qua _ e :: e
e) ins' :: [UID]
ins' -> DefinedQuantityDict -> [UID] -> e -> QDefinition e
forall e. DefinedQuantityDict -> [UID] -> e -> QDefinition e
QD DefinedQuantityDict
qua [UID]
ins' e
e)

qdExpr :: Lens' (QDefinition e) e
qdExpr :: (e -> f e) -> QDefinition e -> f (QDefinition e)
qdExpr = (QDefinition e -> e)
-> (QDefinition e -> e -> QDefinition e)
-> Lens (QDefinition e) (QDefinition e) e e
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens (\(QD _ _ e :: e
e) -> e
e) (\(QD qua :: DefinedQuantityDict
qua ins :: [UID]
ins _) e' :: e
e' -> DefinedQuantityDict -> [UID] -> e -> QDefinition e
forall e. DefinedQuantityDict -> [UID] -> e -> QDefinition e
QD DefinedQuantityDict
qua [UID]
ins e
e')

instance HasUID        (QDefinition e) where uid :: (UID -> f UID) -> QDefinition e -> f (QDefinition e)
uid = (DefinedQuantityDict -> f DefinedQuantityDict)
-> QDefinition e -> f (QDefinition e)
forall e. Lens' (QDefinition e) DefinedQuantityDict
qdQua ((DefinedQuantityDict -> f DefinedQuantityDict)
 -> QDefinition e -> f (QDefinition e))
-> ((UID -> f UID) -> DefinedQuantityDict -> f DefinedQuantityDict)
-> (UID -> f UID)
-> QDefinition e
-> f (QDefinition e)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UID -> f UID) -> DefinedQuantityDict -> f DefinedQuantityDict
forall c. HasUID c => Lens' c UID
uid
instance NamedIdea     (QDefinition e) where term :: (NP -> f NP) -> QDefinition e -> f (QDefinition e)
term = (DefinedQuantityDict -> f DefinedQuantityDict)
-> QDefinition e -> f (QDefinition e)
forall e. Lens' (QDefinition e) DefinedQuantityDict
qdQua ((DefinedQuantityDict -> f DefinedQuantityDict)
 -> QDefinition e -> f (QDefinition e))
-> ((NP -> f NP) -> DefinedQuantityDict -> f DefinedQuantityDict)
-> (NP -> f NP)
-> QDefinition e
-> f (QDefinition e)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (NP -> f NP) -> DefinedQuantityDict -> f DefinedQuantityDict
forall c. NamedIdea c => Lens' c NP
term
instance Idea          (QDefinition e) where getA :: QDefinition e -> Maybe String
getA = DefinedQuantityDict -> Maybe String
forall c. Idea c => c -> Maybe String
getA (DefinedQuantityDict -> Maybe String)
-> (QDefinition e -> DefinedQuantityDict)
-> QDefinition e
-> Maybe String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (QDefinition e
-> Getting DefinedQuantityDict (QDefinition e) DefinedQuantityDict
-> DefinedQuantityDict
forall s a. s -> Getting a s a -> a
^. Getting DefinedQuantityDict (QDefinition e) DefinedQuantityDict
forall e. Lens' (QDefinition e) DefinedQuantityDict
qdQua)
instance HasSpace      (QDefinition e) where typ :: (Space -> f Space) -> QDefinition e -> f (QDefinition e)
typ = (DefinedQuantityDict -> f DefinedQuantityDict)
-> QDefinition e -> f (QDefinition e)
forall e. Lens' (QDefinition e) DefinedQuantityDict
qdQua ((DefinedQuantityDict -> f DefinedQuantityDict)
 -> QDefinition e -> f (QDefinition e))
-> ((Space -> f Space)
    -> DefinedQuantityDict -> f DefinedQuantityDict)
-> (Space -> f Space)
-> QDefinition e
-> f (QDefinition e)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Space -> f Space) -> DefinedQuantityDict -> f DefinedQuantityDict
forall c. HasSpace c => Lens' c Space
typ
instance HasSymbol     (QDefinition e) where symbol :: QDefinition e -> Stage -> Symbol
symbol = DefinedQuantityDict -> Stage -> Symbol
forall c. HasSymbol c => c -> Stage -> Symbol
symbol (DefinedQuantityDict -> Stage -> Symbol)
-> (QDefinition e -> DefinedQuantityDict)
-> QDefinition e
-> Stage
-> Symbol
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (QDefinition e
-> Getting DefinedQuantityDict (QDefinition e) DefinedQuantityDict
-> DefinedQuantityDict
forall s a. s -> Getting a s a -> a
^. Getting DefinedQuantityDict (QDefinition e) DefinedQuantityDict
forall e. Lens' (QDefinition e) DefinedQuantityDict
qdQua)
instance Definition    (QDefinition e) where defn :: (Sentence -> f Sentence) -> QDefinition e -> f (QDefinition e)
defn = (DefinedQuantityDict -> f DefinedQuantityDict)
-> QDefinition e -> f (QDefinition e)
forall e. Lens' (QDefinition e) DefinedQuantityDict
qdQua ((DefinedQuantityDict -> f DefinedQuantityDict)
 -> QDefinition e -> f (QDefinition e))
-> ((Sentence -> f Sentence)
    -> DefinedQuantityDict -> f DefinedQuantityDict)
-> (Sentence -> f Sentence)
-> QDefinition e
-> f (QDefinition e)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Sentence -> f Sentence)
-> DefinedQuantityDict -> f DefinedQuantityDict
forall c. Definition c => Lens' c Sentence
defn
instance Quantity      (QDefinition e) where
instance Eq            (QDefinition e) where a :: QDefinition e
a == :: QDefinition e -> QDefinition e -> Bool
== b :: QDefinition e
b = QDefinition e
a QDefinition e -> Getting UID (QDefinition e) UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID (QDefinition e) UID
forall c. HasUID c => Lens' c UID
uid UID -> UID -> Bool
forall a. Eq a => a -> a -> Bool
== QDefinition e
b QDefinition e -> Getting UID (QDefinition e) UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID (QDefinition e) UID
forall c. HasUID c => Lens' c UID
uid
instance MayHaveUnit   (QDefinition e) where getUnit :: QDefinition e -> Maybe UnitDefn
getUnit = DefinedQuantityDict -> Maybe UnitDefn
forall u. MayHaveUnit u => u -> Maybe UnitDefn
getUnit (DefinedQuantityDict -> Maybe UnitDefn)
-> (QDefinition e -> DefinedQuantityDict)
-> QDefinition e
-> Maybe UnitDefn
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting DefinedQuantityDict (QDefinition e) DefinedQuantityDict
-> QDefinition e -> DefinedQuantityDict
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting DefinedQuantityDict (QDefinition e) DefinedQuantityDict
forall e. Lens' (QDefinition e) DefinedQuantityDict
qdQua
instance DefiningExpr   QDefinition    where defnExpr :: (e -> f e) -> QDefinition e -> f (QDefinition e)
defnExpr = (e -> f e) -> QDefinition e -> f (QDefinition e)
forall e. Lens' (QDefinition e) e
qdExpr
instance Express e => Express (QDefinition e) where
  express :: QDefinition e -> ModelExpr
express q :: QDefinition e
q = ModelExpr -> ModelExpr
f (ModelExpr -> ModelExpr) -> ModelExpr -> ModelExpr
forall a b. (a -> b) -> a -> b
$ e -> ModelExpr
forall c. Express c => c -> ModelExpr
express (e -> ModelExpr) -> e -> ModelExpr
forall a b. (a -> b) -> a -> b
$ QDefinition e
q QDefinition e -> Getting e (QDefinition e) e -> e
forall s a. s -> Getting a s a -> a
^. Getting e (QDefinition e) e
forall (c :: * -> *) e. DefiningExpr c => Lens' (c e) e
defnExpr
    where
      f :: ModelExpr -> ModelExpr
f = case QDefinition e
q QDefinition e -> Getting [UID] (QDefinition e) [UID] -> [UID]
forall s a. s -> Getting a s a -> a
^. Getting [UID] (QDefinition e) [UID]
forall e. Lens' (QDefinition e) [UID]
qdInputs of
        [] -> ModelExpr -> ModelExpr -> ModelExpr
forall r. ModelExprC r => r -> r -> r
defines (QDefinition e -> ModelExpr
forall r c. (ExprC r, HasUID c, HasSymbol c) => c -> r
sy QDefinition e
q)
        is :: [UID]
is -> ModelExpr -> ModelExpr -> ModelExpr
forall r. ModelExprC r => r -> r -> r
defines (ModelExpr -> ModelExpr -> ModelExpr)
-> ModelExpr -> ModelExpr -> ModelExpr
forall a b. (a -> b) -> a -> b
$ QDefinition e -> [ModelExpr] -> ModelExpr
forall r f. (ExprC r, HasUID f, HasSymbol f) => f -> [r] -> r
apply QDefinition e
q ((UID -> ModelExpr) -> [UID] -> [ModelExpr]
forall a b. (a -> b) -> [a] -> [b]
map UID -> ModelExpr
C [UID]
is)
instance ConceptDomain (QDefinition e) where cdom :: QDefinition e -> [UID]
cdom = DefinedQuantityDict -> [UID]
forall c. ConceptDomain c => c -> [UID]
cdom (DefinedQuantityDict -> [UID])
-> (QDefinition e -> DefinedQuantityDict) -> QDefinition e -> [UID]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting DefinedQuantityDict (QDefinition e) DefinedQuantityDict
-> QDefinition e -> DefinedQuantityDict
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting DefinedQuantityDict (QDefinition e) DefinedQuantityDict
forall e. Lens' (QDefinition e) DefinedQuantityDict
qdQua

-- | Create a 'QDefinition' with a 'UID' (as a 'String'), term ('NP'), definition ('Sentence'), 'Symbol',
-- 'Space', unit, and defining expression.
fromEqn :: IsUnit u => String -> NP -> Sentence -> Symbol -> Space -> u -> e -> QDefinition e
fromEqn :: String
-> NP -> Sentence -> Symbol -> Space -> u -> e -> QDefinition e
fromEqn nm :: String
nm desc :: NP
desc def :: Sentence
def symb :: Symbol
symb sp :: Space
sp un :: u
un =
  DefinedQuantityDict -> [UID] -> e -> QDefinition e
forall e. DefinedQuantityDict -> [UID] -> e -> QDefinition e
QD (ConceptChunk -> Symbol -> Space -> u -> DefinedQuantityDict
forall u.
IsUnit u =>
ConceptChunk -> Symbol -> Space -> u -> DefinedQuantityDict
dqd (IdeaDict -> Sentence -> ConceptChunk
forall c. Idea c => c -> Sentence -> ConceptChunk
cc' (String -> NP -> Maybe String -> IdeaDict
mkIdea String
nm NP
desc Maybe String
forall a. Maybe a
Nothing) Sentence
def) Symbol
symb Space
sp u
un) []

-- | Same as 'fromEqn', but has no units.
fromEqn' :: String -> NP -> Sentence -> Symbol -> Space -> e -> QDefinition e
fromEqn' :: String -> NP -> Sentence -> Symbol -> Space -> e -> QDefinition e
fromEqn' nm :: String
nm desc :: NP
desc def :: Sentence
def symb :: Symbol
symb sp :: Space
sp =
  DefinedQuantityDict -> [UID] -> e -> QDefinition e
forall e. DefinedQuantityDict -> [UID] -> e -> QDefinition e
QD (ConceptChunk
-> (Stage -> Symbol)
-> Space
-> Maybe UnitDefn
-> DefinedQuantityDict
dqd' (IdeaDict -> Sentence -> ConceptChunk
forall c. Idea c => c -> Sentence -> ConceptChunk
cc' (String -> NP -> Maybe String -> IdeaDict
mkIdea String
nm NP
desc Maybe String
forall a. Maybe a
Nothing) Sentence
def) (Symbol -> Stage -> Symbol
forall a b. a -> b -> a
const Symbol
symb) Space
sp Maybe UnitDefn
forall a. Maybe a
Nothing) []

-- | Same as 'fromEqn', but symbol depends on stage.
fromEqnSt :: IsUnit u => UID -> NP -> Sentence -> (Stage -> Symbol) ->
  Space -> u -> e -> QDefinition e
fromEqnSt :: UID
-> NP
-> Sentence
-> (Stage -> Symbol)
-> Space
-> u
-> e
-> QDefinition e
fromEqnSt nm :: UID
nm desc :: NP
desc def :: Sentence
def symb :: Stage -> Symbol
symb sp :: Space
sp un :: u
un =
  DefinedQuantityDict -> [UID] -> e -> QDefinition e
forall e. DefinedQuantityDict -> [UID] -> e -> QDefinition e
QD (ConceptChunk
-> (Stage -> Symbol)
-> Space
-> Maybe UnitDefn
-> DefinedQuantityDict
dqd' (IdeaDict -> Sentence -> ConceptChunk
forall c. Idea c => c -> Sentence -> ConceptChunk
cc' (NamedChunk -> IdeaDict
forall c. Idea c => c -> IdeaDict
nw (NamedChunk -> IdeaDict) -> NamedChunk -> IdeaDict
forall a b. (a -> b) -> a -> b
$ UID -> NP -> NamedChunk
ncUID UID
nm NP
desc) Sentence
def) Stage -> Symbol
symb Space
sp (UnitDefn -> Maybe UnitDefn
forall a. a -> Maybe a
Just (UnitDefn -> Maybe UnitDefn) -> UnitDefn -> Maybe UnitDefn
forall a b. (a -> b) -> a -> b
$ u -> UnitDefn
forall u. IsUnit u => u -> UnitDefn
unitWrapper u
un)) []

-- | Same as 'fromEqn', but symbol depends on stage and has no units.
fromEqnSt' :: UID -> NP -> Sentence -> (Stage -> Symbol) -> Space -> e -> QDefinition e
fromEqnSt' :: UID
-> NP
-> Sentence
-> (Stage -> Symbol)
-> Space
-> e
-> QDefinition e
fromEqnSt' nm :: UID
nm desc :: NP
desc def :: Sentence
def symb :: Stage -> Symbol
symb sp :: Space
sp =
  DefinedQuantityDict -> [UID] -> e -> QDefinition e
forall e. DefinedQuantityDict -> [UID] -> e -> QDefinition e
QD (ConceptChunk
-> (Stage -> Symbol)
-> Space
-> Maybe UnitDefn
-> DefinedQuantityDict
dqd' (IdeaDict -> Sentence -> ConceptChunk
forall c. Idea c => c -> Sentence -> ConceptChunk
cc' (NamedChunk -> IdeaDict
forall c. Idea c => c -> IdeaDict
nw (NamedChunk -> IdeaDict) -> NamedChunk -> IdeaDict
forall a b. (a -> b) -> a -> b
$ UID -> NP -> NamedChunk
ncUID UID
nm NP
desc) Sentence
def) Stage -> Symbol
symb Space
sp Maybe UnitDefn
forall a. Maybe a
Nothing) []

-- | Same as 'fromEqnSt'', but takes a 'String' instead of a 'UID'.
fromEqnSt'' :: String -> NP -> Sentence -> (Stage -> Symbol) -> Space -> e ->
  QDefinition e
fromEqnSt'' :: String
-> NP
-> Sentence
-> (Stage -> Symbol)
-> Space
-> e
-> QDefinition e
fromEqnSt'' nm :: String
nm desc :: NP
desc def :: Sentence
def symb :: Stage -> Symbol
symb sp :: Space
sp =
  DefinedQuantityDict -> [UID] -> e -> QDefinition e
forall e. DefinedQuantityDict -> [UID] -> e -> QDefinition e
QD (ConceptChunk
-> (Stage -> Symbol)
-> Space
-> Maybe UnitDefn
-> DefinedQuantityDict
dqd' (IdeaDict -> Sentence -> ConceptChunk
forall c. Idea c => c -> Sentence -> ConceptChunk
cc' (String -> NP -> Maybe String -> IdeaDict
mkIdea String
nm NP
desc Maybe String
forall a. Maybe a
Nothing) Sentence
def) Stage -> Symbol
symb Space
sp Maybe UnitDefn
forall a. Maybe a
Nothing) []

-- | Wrapper for fromEqnSt and fromEqnSt'
mkQDefSt :: UID -> NP -> Sentence -> (Stage -> Symbol) -> Space ->
  Maybe UnitDefn -> e -> QDefinition e
mkQDefSt :: UID
-> NP
-> Sentence
-> (Stage -> Symbol)
-> Space
-> Maybe UnitDefn
-> e
-> QDefinition e
mkQDefSt u :: UID
u n :: NP
n s :: Sentence
s symb :: Stage -> Symbol
symb sp :: Space
sp (Just ud :: UnitDefn
ud) e :: e
e = UID
-> NP
-> Sentence
-> (Stage -> Symbol)
-> Space
-> UnitDefn
-> e
-> QDefinition e
forall u e.
IsUnit u =>
UID
-> NP
-> Sentence
-> (Stage -> Symbol)
-> Space
-> u
-> e
-> QDefinition e
fromEqnSt UID
u NP
n Sentence
s Stage -> Symbol
symb Space
sp UnitDefn
ud e
e
mkQDefSt u :: UID
u n :: NP
n s :: Sentence
s symb :: Stage -> Symbol
symb sp :: Space
sp Nothing   e :: e
e = UID
-> NP
-> Sentence
-> (Stage -> Symbol)
-> Space
-> e
-> QDefinition e
forall e.
UID
-> NP
-> Sentence
-> (Stage -> Symbol)
-> Space
-> e
-> QDefinition e
fromEqnSt' UID
u NP
n Sentence
s Stage -> Symbol
symb Space
sp e
e

-- | Used to help make 'QDefinition's when 'UID', term, and 'Symbol' come from the same source.
mkQuantDef :: (Quantity c, MayHaveUnit c) => c -> e -> QDefinition e
mkQuantDef :: c -> e -> QDefinition e
mkQuantDef c :: c
c = UID
-> NP
-> Sentence
-> (Stage -> Symbol)
-> Space
-> Maybe UnitDefn
-> e
-> QDefinition e
forall e.
UID
-> NP
-> Sentence
-> (Stage -> Symbol)
-> Space
-> Maybe UnitDefn
-> e
-> QDefinition e
mkQDefSt (c
c c -> Getting UID c UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID c UID
forall c. HasUID c => Lens' c UID
uid) (c
c c -> Getting NP c NP -> NP
forall s a. s -> Getting a s a -> a
^. Getting NP c NP
forall c. NamedIdea c => Lens' c NP
term) Sentence
EmptyS (c -> Stage -> Symbol
forall c. HasSymbol c => c -> Stage -> Symbol
symbol c
c) (c
c c -> Getting Space c Space -> Space
forall s a. s -> Getting a s a -> a
^. Getting Space c Space
forall c. HasSpace c => Lens' c Space
typ) (c -> Maybe UnitDefn
forall u. MayHaveUnit u => u -> Maybe UnitDefn
getUnit c
c)

-- FIXME: See #2788.
-- | Used to help make 'QDefinition's when 'UID' and 'Symbol' come from the same source, with the term separate.
mkQuantDef' :: (Quantity c, MayHaveUnit c) => c -> NP -> e -> QDefinition e
mkQuantDef' :: c -> NP -> e -> QDefinition e
mkQuantDef' c :: c
c t :: NP
t = UID
-> NP
-> Sentence
-> (Stage -> Symbol)
-> Space
-> Maybe UnitDefn
-> e
-> QDefinition e
forall e.
UID
-> NP
-> Sentence
-> (Stage -> Symbol)
-> Space
-> Maybe UnitDefn
-> e
-> QDefinition e
mkQDefSt (c
c c -> Getting UID c UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID c UID
forall c. HasUID c => Lens' c UID
uid) NP
t Sentence
EmptyS (c -> Stage -> Symbol
forall c. HasSymbol c => c -> Stage -> Symbol
symbol c
c) (c
c c -> Getting Space c Space -> Space
forall s a. s -> Getting a s a -> a
^. Getting Space c Space
forall c. HasSpace c => Lens' c Space
typ) (c -> Maybe UnitDefn
forall u. MayHaveUnit u => u -> Maybe UnitDefn
getUnit c
c)

-- HACK - makes the definition EmptyS !!! FIXME
-- | Smart constructor for QDefinitions. Requires a quantity and its defining 
-- equation. 
ec :: (Quantity c, MayHaveUnit c) => c -> e -> QDefinition e
ec :: c -> e -> QDefinition e
ec c :: c
c = DefinedQuantityDict -> [UID] -> e -> QDefinition e
forall e. DefinedQuantityDict -> [UID] -> e -> QDefinition e
QD (ConceptChunk
-> (Stage -> Symbol)
-> Space
-> Maybe UnitDefn
-> DefinedQuantityDict
dqd' (IdeaDict -> Sentence -> ConceptChunk
forall c. Idea c => c -> Sentence -> ConceptChunk
cc' (c -> IdeaDict
forall c. Idea c => c -> IdeaDict
nw c
c) Sentence
EmptyS) (c -> Stage -> Symbol
forall c. HasSymbol c => c -> Stage -> Symbol
symbol c
c) (c
c c -> Getting Space c Space -> Space
forall s a. s -> Getting a s a -> a
^. Getting Space c Space
forall c. HasSpace c => Lens' c Space
typ) (c -> Maybe UnitDefn
forall u. MayHaveUnit u => u -> Maybe UnitDefn
getUnit c
c)) []

-- | Factored version of 'QDefinition' functions.
mkFuncDef0 :: (HasUID f, HasSymbol f, HasSpace f,
               HasUID i, HasSymbol i, HasSpace i) =>
  f -> NP -> Sentence -> Maybe UnitDefn -> [i] -> e -> QDefinition e
mkFuncDef0 :: f -> NP -> Sentence -> Maybe UnitDefn -> [i] -> e -> QDefinition e
mkFuncDef0 f :: f
f n :: NP
n s :: Sentence
s u :: Maybe UnitDefn
u is :: [i]
is = DefinedQuantityDict -> [UID] -> e -> QDefinition e
forall e. DefinedQuantityDict -> [UID] -> e -> QDefinition e
QD
  (ConceptChunk
-> (Stage -> Symbol)
-> Space
-> Maybe UnitDefn
-> DefinedQuantityDict
dqd' (IdeaDict -> Sentence -> ConceptChunk
forall c. Idea c => c -> Sentence -> ConceptChunk
cc' (NamedChunk -> IdeaDict
forall c. Idea c => c -> IdeaDict
nw (UID -> NP -> NamedChunk
ncUID (f
f f -> Getting UID f UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID f UID
forall c. HasUID c => Lens' c UID
uid) NP
n)) Sentence
s) (f -> Stage -> Symbol
forall c. HasSymbol c => c -> Stage -> Symbol
symbol f
f)
    ([Space] -> Space -> Space
mkFunction ((i -> Space) -> [i] -> [Space]
forall a b. (a -> b) -> [a] -> [b]
map (i -> Getting Space i Space -> Space
forall s a. s -> Getting a s a -> a
^. Getting Space i Space
forall c. HasSpace c => Lens' c Space
typ) [i]
is) (f
f f -> Getting Space f Space -> Space
forall s a. s -> Getting a s a -> a
^. Getting Space f Space
forall c. HasSpace c => Lens' c Space
typ)) Maybe UnitDefn
u) ((i -> UID) -> [i] -> [UID]
forall a b. (a -> b) -> [a] -> [b]
map (i -> Getting UID i UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID i UID
forall c. HasUID c => Lens' c UID
uid) [i]
is)

-- | Create a 'QDefinition' function with a symbol, name, term, list of inputs, resultant units, and a defining Expr
mkFuncDef :: (HasUID f, HasSymbol f, HasSpace f,
              HasUID i, HasSymbol i, HasSpace i,
              IsUnit u) =>
  f -> NP -> Sentence -> u -> [i] -> e -> QDefinition e
mkFuncDef :: f -> NP -> Sentence -> u -> [i] -> e -> QDefinition e
mkFuncDef f :: f
f n :: NP
n s :: Sentence
s u :: u
u = f -> NP -> Sentence -> Maybe UnitDefn -> [i] -> e -> QDefinition e
forall f i e.
(HasUID f, HasSymbol f, HasSpace f, HasUID i, HasSymbol i,
 HasSpace i) =>
f -> NP -> Sentence -> Maybe UnitDefn -> [i] -> e -> QDefinition e
mkFuncDef0 f
f NP
n Sentence
s (UnitDefn -> Maybe UnitDefn
forall a. a -> Maybe a
Just (UnitDefn -> Maybe UnitDefn) -> UnitDefn -> Maybe UnitDefn
forall a b. (a -> b) -> a -> b
$ u -> UnitDefn
forall u. IsUnit u => u -> UnitDefn
unitWrapper u
u)

-- | Create a 'QDefinition' function with a symbol, name, term, list of inputs, and a defining Expr
mkFuncDef' :: (HasUID f, HasSymbol f, HasSpace f,
               HasUID i, HasSymbol i, HasSpace i) =>
  f -> NP -> Sentence -> [i] -> e -> QDefinition e
mkFuncDef' :: f -> NP -> Sentence -> [i] -> e -> QDefinition e
mkFuncDef' f :: f
f n :: NP
n s :: Sentence
s = f -> NP -> Sentence -> Maybe UnitDefn -> [i] -> e -> QDefinition e
forall f i e.
(HasUID f, HasSymbol f, HasSpace f, HasUID i, HasSymbol i,
 HasSpace i) =>
f -> NP -> Sentence -> Maybe UnitDefn -> [i] -> e -> QDefinition e
mkFuncDef0 f
f NP
n Sentence
s Maybe UnitDefn
forall a. Maybe a
Nothing

-- | Create a 'QDefinition' functions using a symbol, list of inputs, and a defining Expr
mkFuncDefByQ :: (Quantity c, MayHaveUnit c, HasSpace c,
                 Quantity i, HasSpace i) =>
  c -> [i] -> e -> QDefinition e
mkFuncDefByQ :: c -> [i] -> e -> QDefinition e
mkFuncDefByQ f :: c
f = case c -> Maybe UnitDefn
forall u. MayHaveUnit u => u -> Maybe UnitDefn
getUnit c
f of
  Just u :: UnitDefn
u  -> c -> NP -> Sentence -> UnitDefn -> [i] -> e -> QDefinition e
forall f i u e.
(HasUID f, HasSymbol f, HasSpace f, HasUID i, HasSymbol i,
 HasSpace i, IsUnit u) =>
f -> NP -> Sentence -> u -> [i] -> e -> QDefinition e
mkFuncDef  c
f (c
f c -> Getting NP c NP -> NP
forall s a. s -> Getting a s a -> a
^. Getting NP c NP
forall c. NamedIdea c => Lens' c NP
term) Sentence
EmptyS UnitDefn
u
  Nothing -> c -> NP -> Sentence -> [i] -> e -> QDefinition e
forall f i e.
(HasUID f, HasSymbol f, HasSpace f, HasUID i, HasSymbol i,
 HasSpace i) =>
f -> NP -> Sentence -> [i] -> e -> QDefinition e
mkFuncDef' c
f (c
f c -> Getting NP c NP -> NP
forall s a. s -> Getting a s a -> a
^. Getting NP c NP
forall c. NamedIdea c => Lens' c NP
term) Sentence
EmptyS