-- | Defines various NounPhrase-level combinators. These hold more information
-- than those of the Sentence level but may not necessarily have a conceptual link.
-- See the [Wiki](https://github.com/JacquesCarette/Drasil/wiki/Combinator-Documentation)
-- for more information and details about the naming process for combinators.
-- A summary of the function naming scheme is as follows:
-- 
--    * Combinators that conflict with haskell-native functions have an underscore appended.
--    * Default plural case for combinators will be first term singular, second term plural.
--    * @P@ and @S@ denote the plural case of the combinator when it does not follow the above default.
--    * @Gen@ denotes the general function case.
--
-- This module should be used as a qualified import (usually as @NP@),
-- as many function names clash with those in Concepts.hs and Sentence.hs.
module Language.Drasil.NounPhrase.Combinators (
  -- * General Combinator Helper Functions
  insertString, prependString, insertSent, prependSent,
  -- * Prepositions
  -- ** \"The\" Combinators
  the, theGen,
  -- ** \"A\" Combinators
  a_, a_Gen,
  -- * Conjunctions
  -- ** \"And\" Combinators
  and_, and_PS, and_Gen, and_GenGen, andThe,
  -- ** \"The\" Combinators
  ofThe, ofThePS, ofTheGen, inThe, inThePS, inTheGen,
  the_ofThe, the_ofThePS, the_ofTheGen,
  -- ** \"For\" Combinators
  for, forPS, forGen,
  -- ** \"Of\" Combinators
  of_, of_PS, of_Gen, of_GenGen,
  -- ** Other Combinators
  with
) where

import Language.Drasil.NounPhrase
    ( NP,
      CapitalizationRule(CapWords, CapFirst),
      NounPhrase(phraseNP, pluralNP),
      nounPhrase'' )
import Language.Drasil.Sentence ( Sentence(S), (+:+) )
import qualified Language.Drasil.Sentence.Combinators as S


--Maybe move these to a separate Drasil.NounPhrase section
-- | Helper function that places a 'String' in between two 'NP's. Plural case is
-- @(phraseNP t1) +:+ S s +:+ (pluralNP t2)@.
insertString :: String -> NP -> NP -> NP 
insertString :: String -> NP -> NP -> NP
insertString String
s NP
t1 NP
t2 = Sentence
-> Sentence -> CapitalizationRule -> CapitalizationRule -> NP
nounPhrase'' (forall n. NounPhrase n => n -> Sentence
phraseNP NP
t1 Sentence -> Sentence -> Sentence
+:+ String -> Sentence
S String
s Sentence -> Sentence -> Sentence
+:+ forall n. NounPhrase n => n -> Sentence
phraseNP NP
t2) (forall n. NounPhrase n => n -> Sentence
phraseNP NP
t1 Sentence -> Sentence -> Sentence
+:+ String -> Sentence
S String
s Sentence -> Sentence -> Sentence
+:+ forall n. NounPhrase n => n -> Sentence
pluralNP NP
t2) CapitalizationRule
CapFirst CapitalizationRule
CapWords

-- | Helper function that prepends a 'String' to a 'NP'.
prependString :: String -> NP -> NP
prependString :: String -> NP -> NP
prependString String
s NP
t1 = Sentence
-> Sentence -> CapitalizationRule -> CapitalizationRule -> NP
nounPhrase'' (String -> Sentence
S String
s Sentence -> Sentence -> Sentence
+:+ forall n. NounPhrase n => n -> Sentence
phraseNP NP
t1) (String -> Sentence
S String
s Sentence -> Sentence -> Sentence
+:+ forall n. NounPhrase n => n -> Sentence
pluralNP NP
t1) CapitalizationRule
CapFirst CapitalizationRule
CapWords

-- | Helper function that places a 'Sentence' in between two 'NP's. Plural case is
-- @(phraseNP t1) +:+ s +:+ (pluralNP t2)@.
insertSent :: Sentence -> NP -> NP -> NP
insertSent :: Sentence -> NP -> NP -> NP
insertSent Sentence
s NP
t1 NP
t2 = Sentence
-> Sentence -> CapitalizationRule -> CapitalizationRule -> NP
nounPhrase'' (forall n. NounPhrase n => n -> Sentence
phraseNP NP
t1 Sentence -> Sentence -> Sentence
+:+ Sentence
s Sentence -> Sentence -> Sentence
+:+ forall n. NounPhrase n => n -> Sentence
phraseNP NP
t2) (forall n. NounPhrase n => n -> Sentence
phraseNP NP
t1 Sentence -> Sentence -> Sentence
+:+ Sentence
s Sentence -> Sentence -> Sentence
+:+ forall n. NounPhrase n => n -> Sentence
pluralNP NP
t2) CapitalizationRule
CapFirst CapitalizationRule
CapWords

-- | Helper function that prepends a 'Sentence' to a 'NP'.
prependSent :: Sentence -> NP -> NP
prependSent :: Sentence -> NP -> NP
prependSent Sentence
s NP
t1 = Sentence
-> Sentence -> CapitalizationRule -> CapitalizationRule -> NP
nounPhrase'' (Sentence
s Sentence -> Sentence -> Sentence
+:+ forall n. NounPhrase n => n -> Sentence
phraseNP NP
t1) (Sentence
s Sentence -> Sentence -> Sentence
+:+ forall n. NounPhrase n => n -> Sentence
pluralNP NP
t1) CapitalizationRule
CapFirst CapitalizationRule
CapWords


-- | Prepends "the" to a 'NP'.
the :: NP -> NP
the :: NP -> NP
the = String -> NP -> NP
prependString String
"the" 
-- | Similar to 'the', but accepts a function that determines the plural case.
theGen :: (NP -> Sentence) -> NP -> NP
theGen :: (NP -> Sentence) -> NP -> NP
theGen NP -> Sentence
f1 NP
t1 = Sentence
-> Sentence -> CapitalizationRule -> CapitalizationRule -> NP
nounPhrase'' (String -> Sentence
S String
"the" Sentence -> Sentence -> Sentence
+:+ forall n. NounPhrase n => n -> Sentence
phraseNP NP
t1) (String -> Sentence
S String
"the" Sentence -> Sentence -> Sentence
+:+ NP -> Sentence
f1 NP
t1) CapitalizationRule
CapFirst CapitalizationRule
CapWords

-- | Prepends "a" to a 'NP'.
a_ :: NP -> NP
a_ :: NP -> NP
a_ = String -> NP -> NP
prependString String
"a" 
-- | Similar to 'a', but accepts a function that determines the plural case.
a_Gen :: (NP -> Sentence) -> NP -> NP
a_Gen :: (NP -> Sentence) -> NP -> NP
a_Gen NP -> Sentence
f1 NP
t1 = Sentence
-> Sentence -> CapitalizationRule -> CapitalizationRule -> NP
nounPhrase'' (String -> Sentence
S String
"a" Sentence -> Sentence -> Sentence
+:+ forall n. NounPhrase n => n -> Sentence
phraseNP NP
t1) (String -> Sentence
S String
"a" Sentence -> Sentence -> Sentence
+:+ NP -> Sentence
f1 NP
t1) CapitalizationRule
CapFirst CapitalizationRule
CapWords

-- | Inserts "of the" between two 'NP's. Plural case is @(phraseNP t1) +:+ "of the" +:+ (pluralNP t2)@.
ofThe :: NP -> NP -> NP
ofThe :: NP -> NP -> NP
ofThe = String -> NP -> NP -> NP
insertString String
"of the"
-- | Similar to 'ofThe', but the plural case is now @(pluralNP t1) `S.ofThe` (phraseNP t2)@.
ofThePS :: NP -> NP -> NP
ofThePS :: NP -> NP -> NP
ofThePS NP
t1 NP
t2 = Sentence
-> Sentence -> CapitalizationRule -> CapitalizationRule -> NP
nounPhrase'' (forall n. NounPhrase n => n -> Sentence
phraseNP NP
t1 Sentence -> Sentence -> Sentence
`S.ofThe` forall n. NounPhrase n => n -> Sentence
phraseNP NP
t2) (forall n. NounPhrase n => n -> Sentence
pluralNP NP
t1 Sentence -> Sentence -> Sentence
`S.ofThe` forall n. NounPhrase n => n -> Sentence
phraseNP NP
t2) CapitalizationRule
CapFirst CapitalizationRule
CapWords
-- | Similar to 'ofThe', but accepts two functions for the plural case.
ofTheGen :: (NP -> Sentence) -> (NP -> Sentence) -> NP -> NP -> NP
ofTheGen :: (NP -> Sentence) -> (NP -> Sentence) -> NP -> NP -> NP
ofTheGen NP -> Sentence
f1 NP -> Sentence
f2 NP
t1 NP
t2 = Sentence
-> Sentence -> CapitalizationRule -> CapitalizationRule -> NP
nounPhrase'' (forall n. NounPhrase n => n -> Sentence
phraseNP NP
t1 Sentence -> Sentence -> Sentence
`S.ofThe` forall n. NounPhrase n => n -> Sentence
phraseNP NP
t2) (NP -> Sentence
f1 NP
t1 Sentence -> Sentence -> Sentence
`S.ofThe` NP -> Sentence
f2 NP
t2) CapitalizationRule
CapFirst CapitalizationRule
CapWords

-- | Inserts "in the" between two 'NP's. Plural case is @(phraseNP t1) +:+ "in the" +:+ (pluralNP t2)@.
inThe :: NP -> NP -> NP
inThe :: NP -> NP -> NP
inThe = String -> NP -> NP -> NP
insertString String
"in the"
-- | Similar to 'ofThe', but the plural case is now @(pluralNP t1) `S.inThe` (phraseNP t2)@.
inThePS :: NP -> NP -> NP
inThePS :: NP -> NP -> NP
inThePS NP
t1 NP
t2 = Sentence
-> Sentence -> CapitalizationRule -> CapitalizationRule -> NP
nounPhrase'' (forall n. NounPhrase n => n -> Sentence
phraseNP NP
t1 Sentence -> Sentence -> Sentence
`S.inThe` forall n. NounPhrase n => n -> Sentence
phraseNP NP
t2) (forall n. NounPhrase n => n -> Sentence
pluralNP NP
t1 Sentence -> Sentence -> Sentence
`S.inThe` forall n. NounPhrase n => n -> Sentence
phraseNP NP
t2) CapitalizationRule
CapFirst CapitalizationRule
CapWords
-- | Similar to 'ofThe', but accepts two functions for the plural case.
inTheGen :: (NP -> Sentence) -> (NP -> Sentence) -> NP -> NP -> NP
inTheGen :: (NP -> Sentence) -> (NP -> Sentence) -> NP -> NP -> NP
inTheGen NP -> Sentence
f1 NP -> Sentence
f2 NP
t1 NP
t2 = Sentence
-> Sentence -> CapitalizationRule -> CapitalizationRule -> NP
nounPhrase'' (forall n. NounPhrase n => n -> Sentence
phraseNP NP
t1 Sentence -> Sentence -> Sentence
`S.inThe` forall n. NounPhrase n => n -> Sentence
phraseNP NP
t2) (NP -> Sentence
f1 NP
t1 Sentence -> Sentence -> Sentence
`S.inThe` NP -> Sentence
f2 NP
t2) CapitalizationRule
CapFirst CapitalizationRule
CapWords

-- | Prepends "the" and inserts "of the". Plural case is @"the" +:+ (phraseNP t1) +:+ "of the" +:+ (pluralNP t2)@.
the_ofThe :: NP -> NP -> NP
the_ofThe :: NP -> NP -> NP
the_ofThe NP
t1 NP
t2 = NP -> NP
the NP
t1 NP -> NP -> NP
`ofThe` NP
t2
-- | Similar to 'the_ofThe', but the plural case is now @ S "the" +:+ (pluralNP t1) `S.ofThe` (phraseNP t2)@.
the_ofThePS :: NP -> NP -> NP
the_ofThePS :: NP -> NP -> NP
the_ofThePS NP
t1 NP
t2 = NP -> NP
the NP
t1 NP -> NP -> NP
`ofThePS` NP
t2
-- | Similar to 'the_ofThe'', but takes two functions for the plural case.
the_ofTheGen :: (NP -> Sentence) -> (NP -> Sentence) -> NP -> NP -> NP
the_ofTheGen :: (NP -> Sentence) -> (NP -> Sentence) -> NP -> NP -> NP
the_ofTheGen NP -> Sentence
f1 NP -> Sentence
f2 NP
t1 = (NP -> Sentence) -> (NP -> Sentence) -> NP -> NP -> NP
ofTheGen NP -> Sentence
f1 NP -> Sentence
f2 (NP -> NP
the NP
t1)

-- | Inserts "for" between two 'NP's. Plural case is @(phraseNP t1) +:+ "for" +:+ (pluralNP t2)@.
for :: NP -> NP -> NP
for :: NP -> NP -> NP
for = String -> NP -> NP -> NP
insertString String
"for"
-- | Same as 'for', but plural case is now @(pluralNP t1) `S.for` (phraseNP t2)@.
forPS :: NP -> NP -> NP
forPS :: NP -> NP -> NP
forPS NP
t1 NP
t2 = Sentence
-> Sentence -> CapitalizationRule -> CapitalizationRule -> NP
nounPhrase'' (forall n. NounPhrase n => n -> Sentence
phraseNP NP
t1 Sentence -> Sentence -> Sentence
`S.for` forall n. NounPhrase n => n -> Sentence
phraseNP NP
t2) (forall n. NounPhrase n => n -> Sentence
pluralNP NP
t1 Sentence -> Sentence -> Sentence
`S.for` forall n. NounPhrase n => n -> Sentence
phraseNP NP
t2) CapitalizationRule
CapFirst CapitalizationRule
CapWords
-- | Same as 'for'', but takes two functions for the plural case.
forGen :: (NP -> Sentence) -> (NP -> Sentence) -> NP -> NP -> NP
forGen :: (NP -> Sentence) -> (NP -> Sentence) -> NP -> NP -> NP
forGen NP -> Sentence
f1 NP -> Sentence
f2 NP
t1 NP
t2 = Sentence
-> Sentence -> CapitalizationRule -> CapitalizationRule -> NP
nounPhrase'' (forall n. NounPhrase n => n -> Sentence
phraseNP NP
t1 Sentence -> Sentence -> Sentence
`S.for` forall n. NounPhrase n => n -> Sentence
phraseNP NP
t2) (NP -> Sentence
f1 NP
t1 Sentence -> Sentence -> Sentence
`S.for` NP -> Sentence
f2 NP
t2) CapitalizationRule
CapFirst CapitalizationRule
CapWords

-- | Inserts "of" between two 'NP's. Plural case is @(phraseNP t1) +:+ "of" +:+ (pluralNP t2)@.
of_ :: NP -> NP -> NP
of_ :: NP -> NP -> NP
of_ = String -> NP -> NP -> NP
insertString String
"of"
-- | Same as 'of_', but plural case is now @(pluralNP t1) `S.of_` (phraseNP t2)@.
of_PS :: NP -> NP -> NP
of_PS :: NP -> NP -> NP
of_PS NP
t1 NP
t2 = Sentence
-> Sentence -> CapitalizationRule -> CapitalizationRule -> NP
nounPhrase'' (forall n. NounPhrase n => n -> Sentence
phraseNP NP
t1 Sentence -> Sentence -> Sentence
`S.of_` forall n. NounPhrase n => n -> Sentence
phraseNP NP
t2) (forall n. NounPhrase n => n -> Sentence
pluralNP NP
t1 Sentence -> Sentence -> Sentence
`S.of_` forall n. NounPhrase n => n -> Sentence
phraseNP NP
t2) CapitalizationRule
CapFirst CapitalizationRule
CapWords
-- | Same as 'of_', but takes two functions for the plural case.
of_Gen :: (NP -> Sentence) -> (NP -> Sentence) -> NP -> NP -> NP
of_Gen :: (NP -> Sentence) -> (NP -> Sentence) -> NP -> NP -> NP
of_Gen NP -> Sentence
f1 NP -> Sentence
f2 NP
t1 NP
t2 = Sentence
-> Sentence -> CapitalizationRule -> CapitalizationRule -> NP
nounPhrase'' (forall n. NounPhrase n => n -> Sentence
phraseNP NP
t1 Sentence -> Sentence -> Sentence
`S.of_` forall n. NounPhrase n => n -> Sentence
phraseNP NP
t2) (NP -> Sentence
f1 NP
t1 Sentence -> Sentence -> Sentence
`S.of_` NP -> Sentence
f2 NP
t2) CapitalizationRule
CapFirst CapitalizationRule
CapWords
-- | Same as 'of_', but takes two functions for the singular case and two for the plural case.
of_GenGen :: (NP -> Sentence) -> (NP -> Sentence) -> (NP -> Sentence) -> (NP -> Sentence) -> NP -> NP -> NP
of_GenGen :: (NP -> Sentence)
-> (NP -> Sentence)
-> (NP -> Sentence)
-> (NP -> Sentence)
-> NP
-> NP
-> NP
of_GenGen NP -> Sentence
f1 NP -> Sentence
f2 NP -> Sentence
p1 NP -> Sentence
p2 NP
t1 NP
t2 = Sentence
-> Sentence -> CapitalizationRule -> CapitalizationRule -> NP
nounPhrase'' (NP -> Sentence
f1 NP
t1 Sentence -> Sentence -> Sentence
`S.of_` NP -> Sentence
f2 NP
t2) (NP -> Sentence
p1 NP
t1 Sentence -> Sentence -> Sentence
`S.of_` NP -> Sentence
p2 NP
t2) CapitalizationRule
CapFirst CapitalizationRule
CapWords

-- | Inserts "with" between two 'NP's. Plural case is @(phraseNP t1) +:+ "with" +:+ (pluralNP t2)@.
with :: NP -> NP -> NP
with :: NP -> NP -> NP
with = String -> NP -> NP -> NP
insertString String
"with"

-- | Inserts "and" between two 'NP's. Plural case is @(phraseNP t1) +:+ "and" +:+ (pluralNP t2)@.
and_ :: NP -> NP -> NP
and_ :: NP -> NP -> NP
and_ = String -> NP -> NP -> NP
insertString String
"and"
-- | Same as 'and_', but plural case is now @(pluralNP t1) `S.and_` (phraseNP t2)@.
and_PS :: NP -> NP -> NP
and_PS :: NP -> NP -> NP
and_PS NP
t1 NP
t2 = Sentence
-> Sentence -> CapitalizationRule -> CapitalizationRule -> NP
nounPhrase'' (forall n. NounPhrase n => n -> Sentence
phraseNP NP
t1 Sentence -> Sentence -> Sentence
`S.and_` forall n. NounPhrase n => n -> Sentence
phraseNP NP
t2) (forall n. NounPhrase n => n -> Sentence
pluralNP NP
t1 Sentence -> Sentence -> Sentence
`S.and_` forall n. NounPhrase n => n -> Sentence
phraseNP NP
t2) CapitalizationRule
CapFirst CapitalizationRule
CapWords
-- | Same as 'and_', but takes two functions for the plural case.
and_Gen :: (NP -> Sentence) -> (NP -> Sentence) -> NP -> NP -> NP
and_Gen :: (NP -> Sentence) -> (NP -> Sentence) -> NP -> NP -> NP
and_Gen NP -> Sentence
f1 NP -> Sentence
f2 NP
t1 NP
t2 = Sentence
-> Sentence -> CapitalizationRule -> CapitalizationRule -> NP
nounPhrase'' (forall n. NounPhrase n => n -> Sentence
phraseNP NP
t1 Sentence -> Sentence -> Sentence
`S.and_` forall n. NounPhrase n => n -> Sentence
phraseNP NP
t2) (NP -> Sentence
f1 NP
t1 Sentence -> Sentence -> Sentence
`S.and_` NP -> Sentence
f2 NP
t2) CapitalizationRule
CapFirst CapitalizationRule
CapWords
-- | Same as 'and_', but takes two functions for the singular case and two for the plural case.
and_GenGen :: (NP -> Sentence) -> (NP -> Sentence) -> (NP -> Sentence) -> (NP -> Sentence) -> NP -> NP -> NP
and_GenGen :: (NP -> Sentence)
-> (NP -> Sentence)
-> (NP -> Sentence)
-> (NP -> Sentence)
-> NP
-> NP
-> NP
and_GenGen NP -> Sentence
f1 NP -> Sentence
f2 NP -> Sentence
p1 NP -> Sentence
p2 NP
t1 NP
t2 = Sentence
-> Sentence -> CapitalizationRule -> CapitalizationRule -> NP
nounPhrase'' (NP -> Sentence
f1 NP
t1 Sentence -> Sentence -> Sentence
`S.and_` NP -> Sentence
f2 NP
t2) (NP -> Sentence
p1 NP
t1 Sentence -> Sentence -> Sentence
`S.and_` NP -> Sentence
p2 NP
t2) CapitalizationRule
CapFirst CapitalizationRule
CapWords

-- | Inserts "and the" between two 'NP's. Plural case is @(phraseNP t1) +:+ "and the" +:+ (pluralNP t2)@.
andThe :: NP -> NP -> NP
andThe :: NP -> NP -> NP
andThe = String -> NP -> NP -> NP
insertString String
"and the"