<commit_before>{-# LANGUAGE TemplateHaskell, Rank2Types, ScopedTypeVariables, PostfixOperators, GADTs  #-}
-- | Defines types and functions for creating models.
module Theory.Drasil.ModelKinds (
  -- * Types
  ModelKind(..), ModelKinds(..),
  -- * Constructors
  deModel, equationalConstraints, equationalModel, equationalRealm, othModel,
  deModel', equationalConstraints', equationalModel', equationalRealm', othModel',
  equationalModelU, equationalModelN, equationalRealmU, equationalRealmN,
  -- * Lenses
  setMk, elimMk, lensMk,
  -- * Functions
  getEqModQds
  ) where

import Control.Lens (makeLenses, set, lens, to, (^.), Setter', Getter, Lens')
import Data.Maybe (mapMaybe)

import Language.Drasil (NamedIdea(..), NP, QDefinition, HasUID(..), Expr,
  RelationConcept, ConceptDomain(..), Definition(..), Idea(..), Express(..), UID)
import Theory.Drasil.ConstraintSet (ConstraintSet)
import Theory.Drasil.MultiDefn (MultiDefn)
import qualified Language.Drasil.Development as D (uid)

-- | Models can be of different kinds: 
--
--     * 'DEModel's represent differential equations as 'RelationConcept's
--     * 'EquationalConstraint's represent invariants that will hold in a system of equations.
--     * 'EquationalModel's represent quantities that are calculated via a single definition/'QDefinition'.
--     * 'EquationalRealm's represent MultiDefns; quantities that may be calculated using any one of many 'DefiningExpr's (e.g., 'x = A = ... = Z')
--     * 'FunctionalModel's represent quantity-resulting function definitions.
--     * 'OthModel's are placeholders for models. No new 'OthModel's should be created, they should be using one of the other kinds.
data ModelKinds e where
  DEModel               ::              RelationConcept -> ModelKinds e -- TODO: Split into ModelKinds Expr and ModelKinds ModelExpr resulting variants. The Expr variant should carry enough information that it can be solved properly.
  EquationalConstraints ::              ConstraintSet e -> ModelKinds e
  EquationalModel       :: Express e => QDefinition e   -> ModelKinds e
  EquationalRealm       :: Express e => MultiDefn e     -> ModelKinds e
  OthModel              ::              RelationConcept -> ModelKinds e -- TODO: Remove.

-- | 'ModelKinds' carrier, used to carry commonly overwritten information from the IMs/TMs/GDs.
data ModelKind e = MK {
  _mk     :: ModelKinds e,
  _mkUid  :: UID,
  _mkTerm :: NP
}

makeLenses ''ModelKind

-- | Smart constructor for 'DEModel's
deModel :: String -> NP -> RelationConcept -> ModelKind e
deModel u n rc = MK (DEModel rc) (D.uid u) n

-- | Smart constructor for 'DEModel's, deriving UID+Term from the 'RelationConcept'
deModel' :: RelationConcept -> ModelKind e
deModel' rc = MK (DEModel rc) (rc ^. uid) (rc ^. term)

-- | Smart constructor for 'EquationalConstraints'
equationalConstraints :: String -> NP -> ConstraintSet e -> ModelKind e
equationalConstraints u n qs = MK (EquationalConstraints qs) (D.uid u) n

-- | Smart constructor for 'EquationalConstraints', deriving UID+Term from the 'ConstraintSet'
equationalConstraints' :: ConstraintSet e -> ModelKind e
equationalConstraints' qs = MK (EquationalConstraints qs) (qs ^. uid) (qs ^. term)

-- | Smart constructor for 'EquationalModel's
equationalModel :: Express e => String -> NP -> QDefinition e -> ModelKind e
equationalModel u n qd = MK (EquationalModel qd) (D.uid u) n

-- | Smart constructor for 'EquationalModel's, deriving UID+Term from the 'QDefinition'
equationalModel' :: Express e => QDefinition e -> ModelKind e
equationalModel' qd = MK (EquationalModel qd) (qd ^. uid) (qd ^. term)

-- | Smart constructor for 'EquationalModel's, deriving Term from the 'QDefinition'
equationalModelU :: Express e => String -> QDefinition e -> ModelKind e
equationalModelU u qd = MK (EquationalModel qd) (D.uid u) (qd ^. term)

-- | Smart constructor for 'EquationalModel's, deriving UID from the 'QDefinition'
equationalModelN :: Express e => NP -> QDefinition e -> ModelKind e
equationalModelN n qd = MK (EquationalModel qd) (qd ^. uid) n

-- | Smart constructor for 'EquationalRealm's
equationalRealm :: Express e => String -> NP -> MultiDefn e -> ModelKind e
equationalRealm u n md = MK (EquationalRealm md) (D.uid u) n

-- | Smart constructor for 'EquationalRealm's, deriving UID+Term from the 'MultiDefn'
equationalRealm' :: Express e => MultiDefn e -> ModelKind e
equationalRealm' md = MK (EquationalRealm md) (md ^. uid) (md ^. term)

-- | Smart constructor for 'EquationalRealm's
equationalRealmU :: Express e => String -> MultiDefn e -> ModelKind e
equationalRealmU u md = MK (EquationalRealm md) (D.uid u) (md ^. term)

-- | Smart constructor for 'EquationalRealm's, deriving UID from the 'MultiDefn'
equationalRealmN :: Express e => NP -> MultiDefn e -> ModelKind e
equationalRealmN n md = MK (EquationalRealm md) (md ^. uid) n

-- | Smart constructor for 'OthModel's
othModel :: String -> NP -> RelationConcept -> ModelKind Expr
othModel u n rc = MK (OthModel rc) (D.uid u) n

-- | Smart constructor for 'OthModel's, deriving UID+Term from the 'RelationConcept'
othModel' :: RelationConcept -> ModelKind e
othModel' rc = MK (OthModel rc) (rc ^. uid) (rc ^. term)

-- | Finds the 'UID' of the 'ModelKinds'.
instance Express e => HasUID        (ModelKinds e) where uid     = lensMk uid uid uid uid
-- | Finds the term ('NP') of the 'ModelKinds'.
instance Express e => NamedIdea     (ModelKinds e) where term    = lensMk term term term term
-- | Finds the idea of the 'ModelKinds'.
instance Express e => Idea          (ModelKinds e) where getA    = elimMk (to getA) (to getA) (to getA) (to getA)
-- | Finds the definition of the 'ModelKinds'.
instance Express e => Definition    (ModelKinds e) where defn    = lensMk defn defn defn defn
-- | Finds the domain of the 'ModelKinds'.
instance Express e => ConceptDomain (ModelKinds e) where cdom    = elimMk (to cdom) (to cdom) (to cdom) (to cdom)
-- | Rewrites the underlying model using 'ModelExpr'
instance Express e => Express       (ModelKinds e) where express = elimMk (to express) (to express) (to express) (to express)

-- TODO: implement MayHaveUnit for ModelKinds once we've sufficiently removed OthModels & RelationConcepts (else we'd be breaking too much of `stable`)

-- | Finds the 'UID' of the 'ModelKind'.
instance HasUID        (ModelKind e) where uid     = mkUid
-- | Finds the term ('NP') of the 'ModelKind'.
instance NamedIdea     (ModelKind e) where term    = mkTerm
-- | Finds the idea of the 'ModelKind'.
instance Express e => Idea          (ModelKind e) where getA    = getA . (^. mk)
-- | Finds the definition of the 'ModelKind'.
instance Express e => Definition    (ModelKind e) where defn    = mk . defn
-- | Finds the domain of the 'ModelKind'.
instance Express e => ConceptDomain (ModelKind e) where cdom    = cdom . (^. mk)<commit_msg>Tighten restrictions a bit on ModelKinds in preparing to make less restrictive<commit_after>{-# LANGUAGE TemplateHaskell, Rank2Types, ScopedTypeVariables, PostfixOperators, GADTs  #-}
-- | Defines types and functions for creating models.
module Theory.Drasil.ModelKinds (
  -- * Types
  ModelKind(..), ModelKinds(..),
  -- * Constructors
  deModel, equationalConstraints, equationalModel, equationalRealm, othModel,
  deModel', equationalConstraints', equationalModel', equationalRealm', othModel',
  equationalModelU, equationalModelN, equationalRealmU, equationalRealmN,
  -- * Lenses
  setMk, elimMk, lensMk,
  -- * Functions
  getEqModQds
  ) where

import Control.Lens (makeLenses, set, lens, to, (^.), Setter', Getter, Lens')
import Data.Maybe (mapMaybe)

import Language.Drasil (NamedIdea(..), NP, QDefinition, HasUID(..), Expr,
  RelationConcept, ConceptDomain(..), Definition(..), Idea(..), Express(..), UID)
import Theory.Drasil.ConstraintSet (ConstraintSet)
import Theory.Drasil.MultiDefn (MultiDefn)
import qualified Language.Drasil.Development as D (uid)

-- | Models can be of different kinds: 
--
--     * 'DEModel's represent differential equations as 'RelationConcept's
--     * 'EquationalConstraint's represent invariants that will hold in a system of equations.
--     * 'EquationalModel's represent quantities that are calculated via a single definition/'QDefinition'.
--     * 'EquationalRealm's represent MultiDefns; quantities that may be calculated using any one of many 'DefiningExpr's (e.g., 'x = A = ... = Z')
--     * 'FunctionalModel's represent quantity-resulting function definitions.
--     * 'OthModel's are placeholders for models. No new 'OthModel's should be created, they should be using one of the other kinds.
data ModelKinds e where
  DEModel               :: Express e => RelationConcept -> ModelKinds e -- TODO: Split into ModelKinds Expr and ModelKinds ModelExpr resulting variants. The Expr variant should carry enough information that it can be solved properly.
  EquationalConstraints :: Express e => ConstraintSet e -> ModelKinds e
  EquationalModel       :: Express e => QDefinition e   -> ModelKinds e
  EquationalRealm       :: Express e => MultiDefn e     -> ModelKinds e
  OthModel              :: Express e => RelationConcept -> ModelKinds e -- TODO: Remove (after having removed all insances of it).

-- | 'ModelKinds' carrier, used to carry commonly overwritten information from the IMs/TMs/GDs.
data ModelKind e = MK {
  _mk     :: ModelKinds e,
  _mkUid  :: UID,
  _mkTerm :: NP
}

makeLenses ''ModelKind

-- | Smart constructor for 'DEModel's
deModel :: Express e => String -> NP -> RelationConcept -> ModelKind e
deModel u n rc = MK (DEModel rc) (D.uid u) n

-- | Smart constructor for 'DEModel's, deriving UID+Term from the 'RelationConcept'
deModel' :: Express e => RelationConcept -> ModelKind e
deModel' rc = MK (DEModel rc) (rc ^. uid) (rc ^. term)

-- | Smart constructor for 'EquationalConstraints'
equationalConstraints :: Express e => String -> NP -> ConstraintSet e -> ModelKind e
equationalConstraints u n qs = MK (EquationalConstraints qs) (D.uid u) n

-- | Smart constructor for 'EquationalConstraints', deriving UID+Term from the 'ConstraintSet'
equationalConstraints' :: Express e => ConstraintSet e -> ModelKind e
equationalConstraints' qs = MK (EquationalConstraints qs) (qs ^. uid) (qs ^. term)

-- | Smart constructor for 'EquationalModel's
equationalModel :: Express e => String -> NP -> QDefinition e -> ModelKind e
equationalModel u n qd = MK (EquationalModel qd) (D.uid u) n

-- | Smart constructor for 'EquationalModel's, deriving UID+Term from the 'QDefinition'
equationalModel' :: Express e => QDefinition e -> ModelKind e
equationalModel' qd = MK (EquationalModel qd) (qd ^. uid) (qd ^. term)

-- | Smart constructor for 'EquationalModel's, deriving Term from the 'QDefinition'
equationalModelU :: Express e => String -> QDefinition e -> ModelKind e
equationalModelU u qd = MK (EquationalModel qd) (D.uid u) (qd ^. term)

-- | Smart constructor for 'EquationalModel's, deriving UID from the 'QDefinition'
equationalModelN :: Express e => NP -> QDefinition e -> ModelKind e
equationalModelN n qd = MK (EquationalModel qd) (qd ^. uid) n

-- | Smart constructor for 'EquationalRealm's
equationalRealm :: Express e => String -> NP -> MultiDefn e -> ModelKind e
equationalRealm u n md = MK (EquationalRealm md) (D.uid u) n

-- | Smart constructor for 'EquationalRealm's, deriving UID+Term from the 'MultiDefn'
equationalRealm' :: Express e => MultiDefn e -> ModelKind e
equationalRealm' md = MK (EquationalRealm md) (md ^. uid) (md ^. term)

-- | Smart constructor for 'EquationalRealm's
equationalRealmU :: Express e => String -> MultiDefn e -> ModelKind e
equationalRealmU u md = MK (EquationalRealm md) (D.uid u) (md ^. term)

-- | Smart constructor for 'EquationalRealm's, deriving UID from the 'MultiDefn'
equationalRealmN :: Express e => NP -> MultiDefn e -> ModelKind e
equationalRealmN n md = MK (EquationalRealm md) (md ^. uid) n

-- | Smart constructor for 'OthModel's
othModel :: String -> NP -> RelationConcept -> ModelKind Expr
othModel u n rc = MK (OthModel rc) (D.uid u) n

-- | Smart constructor for 'OthModel's, deriving UID+Term from the 'RelationConcept'
othModel' :: Express e => RelationConcept -> ModelKind e
othModel' rc = MK (OthModel rc) (rc ^. uid) (rc ^. term)

-- | Finds the 'UID' of the 'ModelKinds'.
instance Express e => HasUID        (ModelKinds e) where uid     = lensMk uid uid uid uid
-- | Finds the term ('NP') of the 'ModelKinds'.
instance Express e => NamedIdea     (ModelKinds e) where term    = lensMk term term term term
-- | Finds the idea of the 'ModelKinds'.
instance Express e => Idea          (ModelKinds e) where getA    = elimMk (to getA) (to getA) (to getA) (to getA)
-- | Finds the definition of the 'ModelKinds'.
instance Express e => Definition    (ModelKinds e) where defn    = lensMk defn defn defn defn
-- | Finds the domain of the 'ModelKinds'.
instance Express e => ConceptDomain (ModelKinds e) where cdom    = elimMk (to cdom) (to cdom) (to cdom) (to cdom)
-- | Rewrites the underlying model using 'ModelExpr'
instance Express e => Express       (ModelKinds e) where express = elimMk (to express) (to express) (to express) (to express)

-- TODO: implement MayHaveUnit for ModelKinds once we've sufficiently removed OthModels & RelationConcepts (else we'd be breaking too much of `stable`)

-- | Finds the 'UID' of the 'ModelKind'.
instance HasUID        (ModelKind e) where uid     = mkUid
-- | Finds the term ('NP') of the 'ModelKind'.
instance NamedIdea     (ModelKind e) where term    = mkTerm
-- | Finds the idea of the 'ModelKind'.
instance Express e => Idea          (ModelKind e) where getA    = getA . (^. mk)
-- | Finds the definition of the 'ModelKind'.
instance Express e => Definition    (ModelKind e) where defn    = mk . defn
-- | Finds the domain of the 'ModelKind'.
instance Express e => ConceptDomain (ModelKind e) where cdom    = cdom . (^. mk)
{'fraction_non_alphanumeric': 0.11045250831285239, 'fraction_numerical': 0.00014457134595923088, 'mean_word_length': 3.7575653370013753, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 115, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5208452', 'n_tokens_mistral': 4351, 'n_tokens_neox': 4195, 'n_words': 1593}