{-# Language TemplateHaskell #-}
-- | Define concept-related chunks. A concept is usually something that has
-- a term, definition, and comes from some domain of knowledge.
module Language.Drasil.Chunk.Concept.Core(
  -- * Concept-related Datatypes
  ConceptChunk(ConDict), CommonConcept(ComConDict)
  , ConceptInstance(ConInst)
  , sDom)
  where
import Language.Drasil.ShortName (HasShortName(..), ShortName)
import Language.Drasil.Classes (NamedIdea(term), Idea(getA),
  Definition(defn), ConceptDomain(cdom), CommonIdea(abrv))
import Language.Drasil.Chunk.CommonIdea (CI)
import Language.Drasil.Chunk.NamedIdea (IdeaDict)
import Language.Drasil.Label.Type ((+::+), defer, name, raw,
  LblType(..), Referable(..), HasRefAddress(..))
import Language.Drasil.Sentence (Sentence)
import Language.Drasil.UID (UID, HasUID(..))

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

-- | Check if something has one domain. Throws an error if there is more than one.
sDom :: [UID] -> UID
sDom :: [UID] -> UID
sDom [d :: UID
d] = UID
d
sDom d :: [UID]
d = [Char] -> UID
forall a. HasCallStack => [Char] -> a
error ([Char] -> UID) -> [Char] -> UID
forall a b. (a -> b) -> a -> b
$ "Expected ConceptDomain to have a single domain, found " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
  Int -> [Char]
forall a. Show a => a -> [Char]
show ([UID] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [UID]
d) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ " instead."

-- | The ConceptChunk datatype records a concept that contains an idea ('IdeaDict'),
-- a definition ('Sentence'), and an associated domain of knowledge (['UID']).
--
-- Ex. The concept of "Accuracy" may be defined as the quality or state of being correct or precise.
data ConceptChunk = ConDict { ConceptChunk -> IdeaDict
_idea :: IdeaDict -- ^ Contains the idea of the concept.
                            , ConceptChunk -> Sentence
_defn' :: Sentence -- ^ The definition of the concept.
                            , ConceptChunk -> [UID]
cdom' :: [UID] -- ^ Domain of the concept.
                            }
makeLenses ''ConceptChunk

-- | Equal if 'UID's are equal.
instance Eq            ConceptChunk where c1 :: ConceptChunk
c1 == :: ConceptChunk -> ConceptChunk -> Bool
== c2 :: ConceptChunk
c2 = (ConceptChunk
c1 ConceptChunk -> Getting UID ConceptChunk UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID ConceptChunk UID
forall c. HasUID c => Lens' c UID
uid) UID -> UID -> Bool
forall a. Eq a => a -> a -> Bool
== (ConceptChunk
c2 ConceptChunk -> Getting UID ConceptChunk UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID ConceptChunk UID
forall c. HasUID c => Lens' c UID
uid)
-- | Finds 'UID' of the 'IdeaDict' used to make the 'ConceptChunk'.
instance HasUID        ConceptChunk where uid :: (UID -> f UID) -> ConceptChunk -> f ConceptChunk
uid = (IdeaDict -> f IdeaDict) -> ConceptChunk -> f ConceptChunk
Lens' ConceptChunk IdeaDict
idea ((IdeaDict -> f IdeaDict) -> ConceptChunk -> f ConceptChunk)
-> ((UID -> f UID) -> IdeaDict -> f IdeaDict)
-> (UID -> f UID)
-> ConceptChunk
-> f ConceptChunk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UID -> f UID) -> IdeaDict -> f IdeaDict
forall c. HasUID c => Lens' c UID
uid
-- | Finds term ('NP') of the 'IdeaDict' used to make the 'ConceptChunk'.
instance NamedIdea     ConceptChunk where term :: (NP -> f NP) -> ConceptChunk -> f ConceptChunk
term = (IdeaDict -> f IdeaDict) -> ConceptChunk -> f ConceptChunk
Lens' ConceptChunk IdeaDict
idea ((IdeaDict -> f IdeaDict) -> ConceptChunk -> f ConceptChunk)
-> ((NP -> f NP) -> IdeaDict -> f IdeaDict)
-> (NP -> f NP)
-> ConceptChunk
-> f ConceptChunk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (NP -> f NP) -> IdeaDict -> f IdeaDict
forall c. NamedIdea c => Lens' c NP
term
-- | Finds the idea contained in the 'IdeaDict' used to make the 'ConceptChunk'.
instance Idea          ConceptChunk where getA :: ConceptChunk -> Maybe [Char]
getA = IdeaDict -> Maybe [Char]
forall c. Idea c => c -> Maybe [Char]
getA (IdeaDict -> Maybe [Char])
-> (ConceptChunk -> IdeaDict) -> ConceptChunk -> Maybe [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting IdeaDict ConceptChunk IdeaDict -> ConceptChunk -> IdeaDict
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting IdeaDict ConceptChunk IdeaDict
Lens' ConceptChunk IdeaDict
idea
-- | Finds definition of a 'ConceptChunk'.
instance Definition    ConceptChunk where defn :: (Sentence -> f Sentence) -> ConceptChunk -> f ConceptChunk
defn = (Sentence -> f Sentence) -> ConceptChunk -> f ConceptChunk
Lens' ConceptChunk Sentence
defn'
-- | Finds the domain of 'UID's of a 'ConceptChunk'.
instance ConceptDomain ConceptChunk where cdom :: ConceptChunk -> [UID]
cdom = ConceptChunk -> [UID]
cdom'

-- | Contains a common idea ('CI') with a definition ('Sentence').
-- Similar to 'ConceptChunk', but must have an abbreviation.
data CommonConcept = ComConDict { CommonConcept -> CI
_comm :: CI, CommonConcept -> Sentence
_def :: Sentence}
makeLenses ''CommonConcept

-- | Equal if 'UID's are equal.
instance Eq            CommonConcept where c1 :: CommonConcept
c1 == :: CommonConcept -> CommonConcept -> Bool
== c2 :: CommonConcept
c2 = (CommonConcept
c1 CommonConcept -> Getting UID CommonConcept UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID CommonConcept UID
forall c. HasUID c => Lens' c UID
uid) UID -> UID -> Bool
forall a. Eq a => a -> a -> Bool
== (CommonConcept
c2 CommonConcept -> Getting UID CommonConcept UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID CommonConcept UID
forall c. HasUID c => Lens' c UID
uid)
-- | Finds 'UID' of the 'CI' used to make the 'CommonConcept'.
instance HasUID        CommonConcept where uid :: (UID -> f UID) -> CommonConcept -> f CommonConcept
uid = (CI -> f CI) -> CommonConcept -> f CommonConcept
Lens' CommonConcept CI
comm ((CI -> f CI) -> CommonConcept -> f CommonConcept)
-> ((UID -> f UID) -> CI -> f CI)
-> (UID -> f UID)
-> CommonConcept
-> f CommonConcept
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UID -> f UID) -> CI -> f CI
forall c. HasUID c => Lens' c UID
uid
-- | Finds term ('NP') of the 'CI' used to make the 'CommonConcept'.
instance NamedIdea     CommonConcept where term :: (NP -> f NP) -> CommonConcept -> f CommonConcept
term = (CI -> f CI) -> CommonConcept -> f CommonConcept
Lens' CommonConcept CI
comm ((CI -> f CI) -> CommonConcept -> f CommonConcept)
-> ((NP -> f NP) -> CI -> f CI)
-> (NP -> f NP)
-> CommonConcept
-> f CommonConcept
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (NP -> f NP) -> CI -> f CI
forall c. NamedIdea c => Lens' c NP
term
-- | Finds the idea contained in the 'CI' used to make the 'CommonConcept'.
instance Idea          CommonConcept where getA :: CommonConcept -> Maybe [Char]
getA = CI -> Maybe [Char]
forall c. Idea c => c -> Maybe [Char]
getA (CI -> Maybe [Char])
-> (CommonConcept -> CI) -> CommonConcept -> Maybe [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting CI CommonConcept CI -> CommonConcept -> CI
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting CI CommonConcept CI
Lens' CommonConcept CI
comm
-- | Finds definition of a 'CommonConcept'.
instance Definition    CommonConcept where defn :: (Sentence -> f Sentence) -> CommonConcept -> f CommonConcept
defn = (Sentence -> f Sentence) -> CommonConcept -> f CommonConcept
Lens' CommonConcept Sentence
def
-- | Finds the abbreviation contained in the 'CI' used to make the 'CommonConcept'.
instance CommonIdea    CommonConcept where abrv :: CommonConcept -> [Char]
abrv = CI -> [Char]
forall c. CommonIdea c => c -> [Char]
abrv (CI -> [Char]) -> (CommonConcept -> CI) -> CommonConcept -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting CI CommonConcept CI -> CommonConcept -> CI
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting CI CommonConcept CI
Lens' CommonConcept CI
comm
-- | Finds the domain contained in the 'CI' used to make the 'CommonConcept'.
instance ConceptDomain CommonConcept where cdom :: CommonConcept -> [UID]
cdom = CI -> [UID]
forall c. ConceptDomain c => c -> [UID]
cdom (CI -> [UID]) -> (CommonConcept -> CI) -> CommonConcept -> [UID]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting CI CommonConcept CI -> CommonConcept -> CI
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting CI CommonConcept CI
Lens' CommonConcept CI
comm

-- | Contains a 'ConceptChunk', reference address, and a 'ShortName'.
-- It is a concept that can be referred to, or rather, a instance of where a concept is applied.
-- Often used in Goal Statements, Assumptions, Requirements, etc.
--
-- Ex. Something like the assumption that gravity is 9.81 m/s. When we write our equations,
-- we can then link this assumption so that we do not have to explicitly define
-- that assumption when needed to verify our work.
data ConceptInstance = ConInst { ConceptInstance -> ConceptChunk
_cc :: ConceptChunk , ConceptInstance -> [Char]
ra :: String, ConceptInstance -> ShortName
shnm :: ShortName}
makeLenses ''ConceptInstance

-- | Equal if 'UID's are equal.
instance Eq            ConceptInstance where c1 :: ConceptInstance
c1 == :: ConceptInstance -> ConceptInstance -> Bool
== c2 :: ConceptInstance
c2 = (ConceptInstance
c1 ConceptInstance -> Getting UID ConceptInstance UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID ConceptInstance UID
forall c. HasUID c => Lens' c UID
uid) UID -> UID -> Bool
forall a. Eq a => a -> a -> Bool
== (ConceptInstance
c2 ConceptInstance -> Getting UID ConceptInstance UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID ConceptInstance UID
forall c. HasUID c => Lens' c UID
uid)
-- | Finds 'UID' of the 'ConceptChunk' used to make the 'ConceptInstance'.
instance HasUID        ConceptInstance where uid :: (UID -> f UID) -> ConceptInstance -> f ConceptInstance
uid = (ConceptChunk -> f ConceptChunk)
-> ConceptInstance -> f ConceptInstance
Lens' ConceptInstance ConceptChunk
cc ((ConceptChunk -> f ConceptChunk)
 -> ConceptInstance -> f ConceptInstance)
-> ((UID -> f UID) -> ConceptChunk -> f ConceptChunk)
-> (UID -> f UID)
-> ConceptInstance
-> f ConceptInstance
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (IdeaDict -> f IdeaDict) -> ConceptChunk -> f ConceptChunk
Lens' ConceptChunk IdeaDict
idea ((IdeaDict -> f IdeaDict) -> ConceptChunk -> f ConceptChunk)
-> ((UID -> f UID) -> IdeaDict -> f IdeaDict)
-> (UID -> f UID)
-> ConceptChunk
-> f ConceptChunk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UID -> f UID) -> IdeaDict -> f IdeaDict
forall c. HasUID c => Lens' c UID
uid
-- | Finds term ('NP') of the 'ConceptChunk' used to make the 'ConceptInstance'.
instance NamedIdea     ConceptInstance where term :: (NP -> f NP) -> ConceptInstance -> f ConceptInstance
term = (ConceptChunk -> f ConceptChunk)
-> ConceptInstance -> f ConceptInstance
Lens' ConceptInstance ConceptChunk
cc ((ConceptChunk -> f ConceptChunk)
 -> ConceptInstance -> f ConceptInstance)
-> ((NP -> f NP) -> ConceptChunk -> f ConceptChunk)
-> (NP -> f NP)
-> ConceptInstance
-> f ConceptInstance
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (IdeaDict -> f IdeaDict) -> ConceptChunk -> f ConceptChunk
Lens' ConceptChunk IdeaDict
idea ((IdeaDict -> f IdeaDict) -> ConceptChunk -> f ConceptChunk)
-> ((NP -> f NP) -> IdeaDict -> f IdeaDict)
-> (NP -> f NP)
-> ConceptChunk
-> f ConceptChunk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (NP -> f NP) -> IdeaDict -> f IdeaDict
forall c. NamedIdea c => Lens' c NP
term
-- | Finds the idea contained in the 'ConceptChunk' used to make the 'ConceptInstance'.
instance Idea          ConceptInstance where getA :: ConceptInstance -> Maybe [Char]
getA = IdeaDict -> Maybe [Char]
forall c. Idea c => c -> Maybe [Char]
getA (IdeaDict -> Maybe [Char])
-> (ConceptInstance -> IdeaDict) -> ConceptInstance -> Maybe [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting IdeaDict ConceptInstance IdeaDict
-> ConceptInstance -> IdeaDict
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view ((ConceptChunk -> Const IdeaDict ConceptChunk)
-> ConceptInstance -> Const IdeaDict ConceptInstance
Lens' ConceptInstance ConceptChunk
cc ((ConceptChunk -> Const IdeaDict ConceptChunk)
 -> ConceptInstance -> Const IdeaDict ConceptInstance)
-> Getting IdeaDict ConceptChunk IdeaDict
-> Getting IdeaDict ConceptInstance IdeaDict
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting IdeaDict ConceptChunk IdeaDict
Lens' ConceptChunk IdeaDict
idea)
-- | Finds the definition contained in the 'ConceptChunk' used to make the 'ConceptInstance'.
instance Definition    ConceptInstance where defn :: (Sentence -> f Sentence) -> ConceptInstance -> f ConceptInstance
defn = (ConceptChunk -> f ConceptChunk)
-> ConceptInstance -> f ConceptInstance
Lens' ConceptInstance ConceptChunk
cc ((ConceptChunk -> f ConceptChunk)
 -> ConceptInstance -> f ConceptInstance)
-> ((Sentence -> f Sentence) -> ConceptChunk -> f ConceptChunk)
-> (Sentence -> f Sentence)
-> ConceptInstance
-> f ConceptInstance
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Sentence -> f Sentence) -> ConceptChunk -> f ConceptChunk
Lens' ConceptChunk Sentence
defn'
-- | Finds the domain contained in the 'ConceptChunk' used to make the 'ConceptInstance'.
instance ConceptDomain ConceptInstance where cdom :: ConceptInstance -> [UID]
cdom = ConceptChunk -> [UID]
cdom' (ConceptChunk -> [UID])
-> (ConceptInstance -> ConceptChunk) -> ConceptInstance -> [UID]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting ConceptChunk ConceptInstance ConceptChunk
-> ConceptInstance -> ConceptChunk
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting ConceptChunk ConceptInstance ConceptChunk
Lens' ConceptInstance ConceptChunk
cc
-- | Finds the 'ShortName' contained in a 'ConceptInstance'.
instance HasShortName  ConceptInstance where shortname :: ConceptInstance -> ShortName
shortname = ConceptInstance -> ShortName
shnm
-- | Finds the reference address contained in a 'ConceptInstance'.
instance HasRefAddress ConceptInstance where getRefAdd :: ConceptInstance -> LblType
getRefAdd l :: ConceptInstance
l = IRefProg -> [Char] -> LblType
RP (UID -> IRefProg
defer ([UID] -> UID
sDom ([UID] -> UID) -> [UID] -> UID
forall a b. (a -> b) -> a -> b
$ ConceptInstance -> [UID]
forall c. ConceptDomain c => c -> [UID]
cdom ConceptInstance
l) IRefProg -> IRefProg -> IRefProg
+::+ [Char] -> IRefProg
raw ":" IRefProg -> IRefProg -> IRefProg
+::+ IRefProg
name) (ConceptInstance -> [Char]
ra ConceptInstance
l)
-- | Finds the reference information contained in a 'ConceptInstance'.
instance Referable     ConceptInstance where
  refAdd :: ConceptInstance -> [Char]
refAdd      = ConceptInstance -> [Char]
ra        -- Finds the reference address contained in a ConceptInstance.
  renderRef :: ConceptInstance -> LblType
renderRef   = ConceptInstance -> LblType
forall b. HasRefAddress b => b -> LblType
getRefAdd -- Finds the reference address but in a diferent form.