.. Copyright (C) 2001-2019 NLTK Project
.. For license information, see LICENSE.TXT

==============================================
Combinatory Categorial Grammar with semantics
==============================================

-----
Chart
-----


    >>> from nltk.ccg import chart, lexicon
    >>> from nltk.ccg.chart import printCCGDerivation

No semantics
-------------------

    >>> lex = lexicon.fromstring('''
    ...     :- S, NP, N
    ...     She => NP
    ...     has => (S\\NP)/NP
    ...     books => NP
    ...     ''',
    ...     False)

    >>> parser = chart.CCGChartParser(lex, chart.DefaultRuleSet)
    >>> parses = list(parser.parse("She has books".split()))
    >>> print(str(len(parses)) + " parses")
    3 parses

    >>> printCCGDerivation(parses[0])
     She      has      books
     NP   ((S\NP)/NP)   NP
         -------------------->
                (S\NP)
    -------------------------<
                S

    >>> printCCGDerivation(parses[1])
     She      has      books
     NP   ((S\NP)/NP)   NP
    ----->T
    (S/(S\NP))
         -------------------->
                (S\NP)
    ------------------------->
                S


    >>> printCCGDerivation(parses[2])
     She      has      books
     NP   ((S\NP)/NP)   NP
    ----->T
    (S/(S\NP))
    ------------------>B
          (S/NP)
    ------------------------->
                S

Simple semantics
-------------------

    >>> lex = lexicon.fromstring('''
    ...     :- S, NP, N
    ...     She => NP {she}
    ...     has => (S\\NP)/NP {\\x y.have(y, x)}
    ...     a => NP/N {\\P.exists z.P(z)}
    ...     book => N {book}
    ...     ''',
    ...     True)

    >>> parser = chart.CCGChartParser(lex, chart.DefaultRuleSet)
    >>> parses = list(parser.parse("She has a book".split()))
    >>> print(str(len(parses)) + " parses")
    7 parses

    >>> printCCGDerivation(parses[0])
       She                 has                           a                book
     NP {she}  ((S\NP)/NP) {\x y.have(y,x)}  (NP/N) {\P.exists z.P(z)}  N {book}
                                            ------------------------------------->
                                                    NP {exists z.book(z)}
              ------------------------------------------------------------------->
                             (S\NP) {\y.have(y,exists z.book(z))}
    -----------------------------------------------------------------------------<
                           S {have(she,exists z.book(z))}

    >>> printCCGDerivation(parses[1])
       She                 has                           a                book
     NP {she}  ((S\NP)/NP) {\x y.have(y,x)}  (NP/N) {\P.exists z.P(z)}  N {book}
              --------------------------------------------------------->B
                       ((S\NP)/N) {\P y.have(y,exists z.P(z))}
              ------------------------------------------------------------------->
                             (S\NP) {\y.have(y,exists z.book(z))}
    -----------------------------------------------------------------------------<
                           S {have(she,exists z.book(z))}
    
    >>> printCCGDerivation(parses[2])
       She                 has                           a                book
     NP {she}  ((S\NP)/NP) {\x y.have(y,x)}  (NP/N) {\P.exists z.P(z)}  N {book}
    ---------->T
    (S/(S\NP)) {\F.F(she)}
                                            ------------------------------------->
                                                    NP {exists z.book(z)}
              ------------------------------------------------------------------->
                             (S\NP) {\y.have(y,exists z.book(z))}
    ----------------------------------------------------------------------------->
                           S {have(she,exists z.book(z))}

    >>> printCCGDerivation(parses[3])
       She                 has                           a                book
     NP {she}  ((S\NP)/NP) {\x y.have(y,x)}  (NP/N) {\P.exists z.P(z)}  N {book}
    ---------->T
    (S/(S\NP)) {\F.F(she)}
              --------------------------------------------------------->B
                       ((S\NP)/N) {\P y.have(y,exists z.P(z))}
              ------------------------------------------------------------------->
                             (S\NP) {\y.have(y,exists z.book(z))}
    ----------------------------------------------------------------------------->
                           S {have(she,exists z.book(z))}

    >>> printCCGDerivation(parses[4])
       She                 has                           a                book
     NP {she}  ((S\NP)/NP) {\x y.have(y,x)}  (NP/N) {\P.exists z.P(z)}  N {book}
    ---------->T
    (S/(S\NP)) {\F.F(she)}
    ---------------------------------------->B
            (S/NP) {\x.have(she,x)}
                                            ------------------------------------->
                                                    NP {exists z.book(z)}
    ----------------------------------------------------------------------------->
                           S {have(she,exists z.book(z))}

    >>> printCCGDerivation(parses[5])
       She                 has                           a                book
     NP {she}  ((S\NP)/NP) {\x y.have(y,x)}  (NP/N) {\P.exists z.P(z)}  N {book}
    ---------->T
    (S/(S\NP)) {\F.F(she)}
              --------------------------------------------------------->B
                       ((S\NP)/N) {\P y.have(y,exists z.P(z))}
    ------------------------------------------------------------------->B
                    (S/N) {\P.have(she,exists z.P(z))}
    ----------------------------------------------------------------------------->
                           S {have(she,exists z.book(z))}

    >>> printCCGDerivation(parses[6])
       She                 has                           a                book
     NP {she}  ((S\NP)/NP) {\x y.have(y,x)}  (NP/N) {\P.exists z.P(z)}  N {book}
    ---------->T
    (S/(S\NP)) {\F.F(she)}
    ---------------------------------------->B
            (S/NP) {\x.have(she,x)}
    ------------------------------------------------------------------->B
                    (S/N) {\P.have(she,exists z.P(z))}
    ----------------------------------------------------------------------------->
                           S {have(she,exists z.book(z))}

Complex semantics
-------------------

    >>> lex = lexicon.fromstring('''
    ...     :- S, NP, N
    ...     She => NP {she}
    ...     has => (S\\NP)/NP {\\x y.have(y, x)}
    ...     a => ((S\\NP)\\((S\\NP)/NP))/N {\\P R x.(exists z.P(z) & R(z,x))}
    ...     book => N {book}
    ...     ''',
    ...     True)

    >>> parser = chart.CCGChartParser(lex, chart.DefaultRuleSet)
    >>> parses = list(parser.parse("She has a book".split()))
    >>> print(str(len(parses)) + " parses")
    2 parses

    >>> printCCGDerivation(parses[0])
       She                 has                                           a                                 book
     NP {she}  ((S\NP)/NP) {\x y.have(y,x)}  (((S\NP)\((S\NP)/NP))/N) {\P R x.(exists z.P(z) & R(z,x))}  N {book}
                                            ---------------------------------------------------------------------->
                                                   ((S\NP)\((S\NP)/NP)) {\R x.(exists z.book(z) & R(z,x))}
              ----------------------------------------------------------------------------------------------------<
                                           (S\NP) {\x.(exists z.book(z) & have(x,z))}
    --------------------------------------------------------------------------------------------------------------<
                                         S {(exists z.book(z) & have(she,z))}

    >>> printCCGDerivation(parses[1])
       She                 has                                           a                                 book
     NP {she}  ((S\NP)/NP) {\x y.have(y,x)}  (((S\NP)\((S\NP)/NP))/N) {\P R x.(exists z.P(z) & R(z,x))}  N {book}
    ---------->T
    (S/(S\NP)) {\F.F(she)}
                                            ---------------------------------------------------------------------->
                                                   ((S\NP)\((S\NP)/NP)) {\R x.(exists z.book(z) & R(z,x))}
              ----------------------------------------------------------------------------------------------------<
                                           (S\NP) {\x.(exists z.book(z) & have(x,z))}
    -------------------------------------------------------------------------------------------------------------->
                                         S {(exists z.book(z) & have(she,z))}

Using conjunctions
---------------------

    # TODO: The semantics of "and" should have been more flexible
    >>> lex = lexicon.fromstring('''
    ...     :- S, NP, N
    ...     I => NP {I}
    ...     cook => (S\\NP)/NP {\\x y.cook(x,y)}
    ...     and => var\\.,var/.,var {\\P Q x y.(P(x,y) & Q(x,y))}
    ...     eat => (S\\NP)/NP {\\x y.eat(x,y)}
    ...     the => NP/N {\\x.the(x)}
    ...     bacon => N {bacon}
    ...     ''',
    ...     True)

    >>> parser = chart.CCGChartParser(lex, chart.DefaultRuleSet)
    >>> parses = list(parser.parse("I cook and eat the bacon".split()))
    >>> print(str(len(parses)) + " parses")
    7 parses

    >>> printCCGDerivation(parses[0])
       I                 cook                                       and                                        eat                     the            bacon
     NP {I}  ((S\NP)/NP) {\x y.cook(x,y)}  ((_var0\.,_var0)/.,_var0) {\P Q x y.(P(x,y) & Q(x,y))}  ((S\NP)/NP) {\x y.eat(x,y)}  (NP/N) {\x.the(x)}  N {bacon}
                                          ------------------------------------------------------------------------------------->
                                                        (((S\NP)/NP)\.,((S\NP)/NP)) {\Q x y.(eat(x,y) & Q(x,y))}
            -------------------------------------------------------------------------------------------------------------------<
                                                 ((S\NP)/NP) {\x y.(eat(x,y) & cook(x,y))}
                                                                                                                               ------------------------------->
                                                                                                                                       NP {the(bacon)}
            -------------------------------------------------------------------------------------------------------------------------------------------------->
                                                           (S\NP) {\y.(eat(the(bacon),y) & cook(the(bacon),y))}
    ----------------------------------------------------------------------------------------------------------------------------------------------------------<
                                                           S {(eat(the(bacon),I) & cook(the(bacon),I))}

    >>> printCCGDerivation(parses[1])
       I                 cook                                       and                                        eat                     the            bacon
     NP {I}  ((S\NP)/NP) {\x y.cook(x,y)}  ((_var0\.,_var0)/.,_var0) {\P Q x y.(P(x,y) & Q(x,y))}  ((S\NP)/NP) {\x y.eat(x,y)}  (NP/N) {\x.the(x)}  N {bacon}
                                          ------------------------------------------------------------------------------------->
                                                        (((S\NP)/NP)\.,((S\NP)/NP)) {\Q x y.(eat(x,y) & Q(x,y))}
            -------------------------------------------------------------------------------------------------------------------<
                                                 ((S\NP)/NP) {\x y.(eat(x,y) & cook(x,y))}
            --------------------------------------------------------------------------------------------------------------------------------------->B
                                                      ((S\NP)/N) {\x y.(eat(the(x),y) & cook(the(x),y))}
            -------------------------------------------------------------------------------------------------------------------------------------------------->
                                                           (S\NP) {\y.(eat(the(bacon),y) & cook(the(bacon),y))}
    ----------------------------------------------------------------------------------------------------------------------------------------------------------<
                                                           S {(eat(the(bacon),I) & cook(the(bacon),I))}

    >>> printCCGDerivation(parses[2])
       I                 cook                                       and                                        eat                     the            bacon
     NP {I}  ((S\NP)/NP) {\x y.cook(x,y)}  ((_var0\.,_var0)/.,_var0) {\P Q x y.(P(x,y) & Q(x,y))}  ((S\NP)/NP) {\x y.eat(x,y)}  (NP/N) {\x.the(x)}  N {bacon}
    -------->T
    (S/(S\NP)) {\F.F(I)}
                                          ------------------------------------------------------------------------------------->
                                                        (((S\NP)/NP)\.,((S\NP)/NP)) {\Q x y.(eat(x,y) & Q(x,y))}
            -------------------------------------------------------------------------------------------------------------------<
                                                 ((S\NP)/NP) {\x y.(eat(x,y) & cook(x,y))}
                                                                                                                               ------------------------------->
                                                                                                                                       NP {the(bacon)}
            -------------------------------------------------------------------------------------------------------------------------------------------------->
                                                           (S\NP) {\y.(eat(the(bacon),y) & cook(the(bacon),y))}
    ---------------------------------------------------------------------------------------------------------------------------------------------------------->
                                                           S {(eat(the(bacon),I) & cook(the(bacon),I))}

    >>> printCCGDerivation(parses[3])
       I                 cook                                       and                                        eat                     the            bacon
     NP {I}  ((S\NP)/NP) {\x y.cook(x,y)}  ((_var0\.,_var0)/.,_var0) {\P Q x y.(P(x,y) & Q(x,y))}  ((S\NP)/NP) {\x y.eat(x,y)}  (NP/N) {\x.the(x)}  N {bacon}
    -------->T
    (S/(S\NP)) {\F.F(I)}
                                          ------------------------------------------------------------------------------------->
                                                        (((S\NP)/NP)\.,((S\NP)/NP)) {\Q x y.(eat(x,y) & Q(x,y))}
            -------------------------------------------------------------------------------------------------------------------<
                                                 ((S\NP)/NP) {\x y.(eat(x,y) & cook(x,y))}
            --------------------------------------------------------------------------------------------------------------------------------------->B
                                                      ((S\NP)/N) {\x y.(eat(the(x),y) & cook(the(x),y))}
            -------------------------------------------------------------------------------------------------------------------------------------------------->
                                                           (S\NP) {\y.(eat(the(bacon),y) & cook(the(bacon),y))}
    ---------------------------------------------------------------------------------------------------------------------------------------------------------->
                                                           S {(eat(the(bacon),I) & cook(the(bacon),I))}

    >>> printCCGDerivation(parses[4])
       I                 cook                                       and                                        eat                     the            bacon
     NP {I}  ((S\NP)/NP) {\x y.cook(x,y)}  ((_var0\.,_var0)/.,_var0) {\P Q x y.(P(x,y) & Q(x,y))}  ((S\NP)/NP) {\x y.eat(x,y)}  (NP/N) {\x.the(x)}  N {bacon}
    -------->T
    (S/(S\NP)) {\F.F(I)}
                                          ------------------------------------------------------------------------------------->
                                                        (((S\NP)/NP)\.,((S\NP)/NP)) {\Q x y.(eat(x,y) & Q(x,y))}
            -------------------------------------------------------------------------------------------------------------------<
                                                 ((S\NP)/NP) {\x y.(eat(x,y) & cook(x,y))}
    --------------------------------------------------------------------------------------------------------------------------->B
                                                (S/NP) {\x.(eat(x,I) & cook(x,I))}
                                                                                                                               ------------------------------->
                                                                                                                                       NP {the(bacon)}
    ---------------------------------------------------------------------------------------------------------------------------------------------------------->
                                                           S {(eat(the(bacon),I) & cook(the(bacon),I))}

    >>> printCCGDerivation(parses[5])
       I                 cook                                       and                                        eat                     the            bacon
     NP {I}  ((S\NP)/NP) {\x y.cook(x,y)}  ((_var0\.,_var0)/.,_var0) {\P Q x y.(P(x,y) & Q(x,y))}  ((S\NP)/NP) {\x y.eat(x,y)}  (NP/N) {\x.the(x)}  N {bacon}
    -------->T
    (S/(S\NP)) {\F.F(I)}
                                          ------------------------------------------------------------------------------------->
                                                        (((S\NP)/NP)\.,((S\NP)/NP)) {\Q x y.(eat(x,y) & Q(x,y))}
            -------------------------------------------------------------------------------------------------------------------<
                                                 ((S\NP)/NP) {\x y.(eat(x,y) & cook(x,y))}
            --------------------------------------------------------------------------------------------------------------------------------------->B
                                                      ((S\NP)/N) {\x y.(eat(the(x),y) & cook(the(x),y))}
    ----------------------------------------------------------------------------------------------------------------------------------------------->B
                                                      (S/N) {\x.(eat(the(x),I) & cook(the(x),I))}
    ---------------------------------------------------------------------------------------------------------------------------------------------------------->
                                                           S {(eat(the(bacon),I) & cook(the(bacon),I))}

    >>> printCCGDerivation(parses[6])
       I                 cook                                       and                                        eat                     the            bacon
     NP {I}  ((S\NP)/NP) {\x y.cook(x,y)}  ((_var0\.,_var0)/.,_var0) {\P Q x y.(P(x,y) & Q(x,y))}  ((S\NP)/NP) {\x y.eat(x,y)}  (NP/N) {\x.the(x)}  N {bacon}
    -------->T
    (S/(S\NP)) {\F.F(I)}
                                          ------------------------------------------------------------------------------------->
                                                        (((S\NP)/NP)\.,((S\NP)/NP)) {\Q x y.(eat(x,y) & Q(x,y))}
            -------------------------------------------------------------------------------------------------------------------<
                                                 ((S\NP)/NP) {\x y.(eat(x,y) & cook(x,y))}
    --------------------------------------------------------------------------------------------------------------------------->B
                                                (S/NP) {\x.(eat(x,I) & cook(x,I))}
    ----------------------------------------------------------------------------------------------------------------------------------------------->B
                                                      (S/N) {\x.(eat(the(x),I) & cook(the(x),I))}
    ---------------------------------------------------------------------------------------------------------------------------------------------------------->
                                                           S {(eat(the(bacon),I) & cook(the(bacon),I))}

Tests from published papers
------------------------------

An example from "CCGbank: A Corpus of CCG Derivations and Dependency Structures Extracted from the Penn Treebank", Hockenmaier and Steedman, 2007, Page 359, https://www.aclweb.org/anthology/J/J07/J07-3004.pdf

    >>> lex = lexicon.fromstring('''
    ...     :- S, NP
    ...     I => NP {I}
    ...     give => ((S\\NP)/NP)/NP {\\x y z.give(y,x,z)}
    ...     them => NP {them}
    ...     money => NP {money}
    ...     ''',
    ...     True)

    >>> parser = chart.CCGChartParser(lex, chart.DefaultRuleSet)
    >>> parses = list(parser.parse("I give them money".split()))
    >>> print(str(len(parses)) + " parses")
    3 parses

    >>> printCCGDerivation(parses[0])
       I                     give                     them       money
     NP {I}  (((S\NP)/NP)/NP) {\x y z.give(y,x,z)}  NP {them}  NP {money}
            -------------------------------------------------->
                    ((S\NP)/NP) {\y z.give(y,them,z)}
            -------------------------------------------------------------->
                            (S\NP) {\z.give(money,them,z)}
    ----------------------------------------------------------------------<
                            S {give(money,them,I)}

    >>> printCCGDerivation(parses[1])
       I                     give                     them       money
     NP {I}  (((S\NP)/NP)/NP) {\x y z.give(y,x,z)}  NP {them}  NP {money}
    -------->T
    (S/(S\NP)) {\F.F(I)}
            -------------------------------------------------->
                    ((S\NP)/NP) {\y z.give(y,them,z)}
            -------------------------------------------------------------->
                            (S\NP) {\z.give(money,them,z)}
    ---------------------------------------------------------------------->
                            S {give(money,them,I)}

    
    >>> printCCGDerivation(parses[2])
       I                     give                     them       money
     NP {I}  (((S\NP)/NP)/NP) {\x y z.give(y,x,z)}  NP {them}  NP {money}
    -------->T
    (S/(S\NP)) {\F.F(I)}
            -------------------------------------------------->
                    ((S\NP)/NP) {\y z.give(y,them,z)}
    ---------------------------------------------------------->B
                    (S/NP) {\y.give(y,them,I)}
    ---------------------------------------------------------------------->
                            S {give(money,them,I)}


An example from "CCGbank: A Corpus of CCG Derivations and Dependency Structures Extracted from the Penn Treebank", Hockenmaier and Steedman, 2007, Page 359, https://www.aclweb.org/anthology/J/J07/J07-3004.pdf

    >>> lex = lexicon.fromstring('''
    ...     :- N, NP, S
    ...     money => N {money}
    ...     that => (N\\N)/(S/NP) {\\P Q x.(P(x) & Q(x))}
    ...     I => NP {I}
    ...     give => ((S\\NP)/NP)/NP {\\x y z.give(y,x,z)}
    ...     them => NP {them}
    ...     ''',
    ...     True)

    >>> parser = chart.CCGChartParser(lex, chart.DefaultRuleSet)
    >>> parses = list(parser.parse("money that I give them".split()))
    >>> print(str(len(parses)) + " parses")
    3 parses

    >>> printCCGDerivation(parses[0])
       money                    that                     I                     give                     them
     N {money}  ((N\N)/(S/NP)) {\P Q x.(P(x) & Q(x))}  NP {I}  (((S\NP)/NP)/NP) {\x y z.give(y,x,z)}  NP {them}
                                                      -------->T
                                                (S/(S\NP)) {\F.F(I)}
                                                              -------------------------------------------------->
                                                                      ((S\NP)/NP) {\y z.give(y,them,z)}
                                                      ---------------------------------------------------------->B
                                                                      (S/NP) {\y.give(y,them,I)}
               ------------------------------------------------------------------------------------------------->
                                             (N\N) {\Q x.(give(x,them,I) & Q(x))}
    ------------------------------------------------------------------------------------------------------------<
                                         N {\x.(give(x,them,I) & money(x))}

    >>> printCCGDerivation(parses[1])
       money                    that                     I                     give                     them
     N {money}  ((N\N)/(S/NP)) {\P Q x.(P(x) & Q(x))}  NP {I}  (((S\NP)/NP)/NP) {\x y z.give(y,x,z)}  NP {them}
    ----------->T
    (N/(N\N)) {\F.F(money)}
                                                      -------->T
                                                (S/(S\NP)) {\F.F(I)}
                                                              -------------------------------------------------->
                                                                      ((S\NP)/NP) {\y z.give(y,them,z)}
                                                      ---------------------------------------------------------->B
                                                                      (S/NP) {\y.give(y,them,I)}
               ------------------------------------------------------------------------------------------------->
                                             (N\N) {\Q x.(give(x,them,I) & Q(x))}
    ------------------------------------------------------------------------------------------------------------>
                                         N {\x.(give(x,them,I) & money(x))}

    >>> printCCGDerivation(parses[2])
       money                    that                     I                     give                     them
     N {money}  ((N\N)/(S/NP)) {\P Q x.(P(x) & Q(x))}  NP {I}  (((S\NP)/NP)/NP) {\x y z.give(y,x,z)}  NP {them}
    ----------->T
    (N/(N\N)) {\F.F(money)}
    -------------------------------------------------->B
           (N/(S/NP)) {\P x.(P(x) & money(x))}
                                                      -------->T
                                                (S/(S\NP)) {\F.F(I)}
                                                              -------------------------------------------------->
                                                                      ((S\NP)/NP) {\y z.give(y,them,z)}
                                                      ---------------------------------------------------------->B
                                                                      (S/NP) {\y.give(y,them,I)}
    ------------------------------------------------------------------------------------------------------------>
                                         N {\x.(give(x,them,I) & money(x))}


-------
Lexicon
-------

    >>> from nltk.ccg import lexicon

Parse lexicon with semantics

    >>> print(str(lexicon.fromstring(
    ...     '''
    ...     :- S,NP
    ...
    ...     IntransVsg :: S\\NP[sg]
    ...     
    ...     sleeps => IntransVsg {\\x.sleep(x)}
    ...     eats => S\\NP[sg]/NP {\\x y.eat(x,y)}
    ...        
    ...     and => var\\var/var {\\x y.x & y}
    ...     ''',
    ...     True
    ... )))
    and => ((_var0\_var0)/_var0) {(\x y.x & y)}
    eats => ((S\NP['sg'])/NP) {\x y.eat(x,y)}
    sleeps => (S\NP['sg']) {\x.sleep(x)}

Parse lexicon without semantics

    >>> print(str(lexicon.fromstring(
    ...     '''
    ...     :- S,NP
    ...
    ...     IntransVsg :: S\\NP[sg]
    ...     
    ...     sleeps => IntransVsg
    ...     eats => S\\NP[sg]/NP {sem=\\x y.eat(x,y)}
    ...        
    ...     and => var\\var/var
    ...     ''',
    ...     False
    ... )))
    and => ((_var0\_var0)/_var0)
    eats => ((S\NP['sg'])/NP)
    sleeps => (S\NP['sg'])

Semantics are missing

    >>> print(str(lexicon.fromstring(
    ...     '''
    ...     :- S,NP
    ...     
    ...     eats => S\\NP[sg]/NP
    ...     ''',
    ...     True
    ... )))
    Traceback (most recent call last):
      ...
    AssertionError: eats => S\NP[sg]/NP must contain semantics because include_semantics is set to True


------------------------------------
CCG combinator semantics computation
------------------------------------

    >>> from nltk.sem.logic import *
    >>> from nltk.ccg.logic import *

    >>> read_expr = Expression.fromstring

Compute semantics from function application

    >>> print(str(compute_function_semantics(read_expr(r'\x.P(x)'), read_expr(r'book'))))
    P(book)

    >>> print(str(compute_function_semantics(read_expr(r'\P.P(book)'), read_expr(r'read'))))
    read(book)

    >>> print(str(compute_function_semantics(read_expr(r'\P.P(book)'), read_expr(r'\x.read(x)'))))
    read(book)

Compute semantics from composition

    >>> print(str(compute_composition_semantics(read_expr(r'\x.P(x)'), read_expr(r'\x.Q(x)'))))
    \x.P(Q(x))

    >>> print(str(compute_composition_semantics(read_expr(r'\x.P(x)'), read_expr(r'read'))))
    Traceback (most recent call last):
      ...
    AssertionError: `read` must be a lambda expression

Compute semantics from substitution

    >>> print(str(compute_substitution_semantics(read_expr(r'\x y.P(x,y)'), read_expr(r'\x.Q(x)'))))
    \x.P(x,Q(x))
    
    >>> print(str(compute_substitution_semantics(read_expr(r'\x.P(x)'), read_expr(r'read'))))
    Traceback (most recent call last):
      ...
    AssertionError: `\x.P(x)` must be a lambda expression with 2 arguments

Compute type-raise semantics

    >>> print(str(compute_type_raised_semantics(read_expr(r'\x.P(x)'))))
    \F x.F(P(x))

    >>> print(str(compute_type_raised_semantics(read_expr(r'\x.F(x)'))))
    \F1 x.F1(F(x))

    >>> print(str(compute_type_raised_semantics(read_expr(r'\x y z.P(x,y,z)'))))
    \F x y z.F(P(x,y,z))

