{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# The Lambda Notebook\n", "\n", "Welcome to the [Lambda Notebook](http://lambdanotebook.com/)! This is a tool building on [Jupyter](http://jupyter.org/) that aims to computationally implement the core tools involved in linguistic semantics and pragmatics. The focus is on discrete tools involving logic and the lambda calculus that are the building blocks of theories of compositional semantics in linguistics. Because the project builds on and is well-integrated with Jupyter, it inherits many extremely powerful tools aimed at scientific and interactive computing. Some use cases for the lambda notebook include:\n", "\n", "* doing and verifying calculations involving typed lambda calculus\n", "* doing and verifying calculations involving (mostly first-order) logics (including propositional / predicate logic, but also variants and enhanced systems)\n", "* implementing a paper's analysis in order to understand it better\n", "* writing '*digital fragments*' -- working implementations of a compositional analysis or system developed in the course of linguistics research. These could form an appendix or supplementary materials to a paper\n", "* implementing a computational semantics model that makes use of core linguistic theory\n", "* Using tools like [quarto](https://quarto.org/) to render linguistic semantics for the web\n", "* ...\n", "\n", "The rest of this document introduces some key concepts about using the lambda notebook targeting linguists who have basic knowledge of semantics, logic, and compositionality (but not necessarily python/Jupyter)\n", "\n", " 1. [Basics](#Basics)\n", " 2. [Lambda notebook cells](#Lambda-notebook-cells)\n", " 3. [Overview of key features](#Overview-of-key-features)\n", " 4. [Interface and background on Jupyter](#Interface-and-background-on-Jupyter)\n", " \n", "Quick links: [Quick reference.ipynb](/notebooks/documentation/Quick reference.ipynb) | [Metalanguage documentation.ipynb](/notebooks/documentation/Metalanguage documentation.ipynb)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Basics\n", "\n", "**Notebooks:** Jupyter Notebook is a particular interface to IPython (and other languages) inspired originally by mathematica notebooks, and is centered around interleaving code with documentation. The lambda notebook is primarily intended to be used in the context of a Jupyter notebook (though it does not need to be).\n", "\n", "**Cells and running code:** Jupyter Notebooks are structured into cells. Each cell contains code or text (typically markdown formatted text). Ordinary code cells contain python code that (in an interactive notebook setting) can be run: To (re-)run a cell you can hit the run button in the toolbar with the cell selected, or hit shift+enter while the cell is selected. A code cell by default has an \"output\" determined by the last executable line of the cell: as long as the value of this line is not `None`, is displayed when the cell is executed. Other code can explicitly display output, e.g. via `print`.\n", "\n", "If you are viewing this as an interactive notebook, you can hit *shift+enter* or use the run button on the following cell to see a basic example of a regular python cell:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"This is the output of a python print command (but not the output of the cell).\")\n", "20 + 22" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Magics:** The lambda notebook relies on a specific kind of cell involving IPython \"magics\" to do things like interpret lambda calculus expressions. These magics change the mode of the cell or line into one that parse lambda notebook-specific code. Magics that transform an entire cell are indicated by a `%%` on the first line, and that transform a line are indicated by a `%`. (Advanced note: line magics can involve part of a line of python code.)\n", "\n", "## Lambda notebook cells and objects\n", "\n", "One main lambda notebook cell magic is the `%%lamb` magic. If a cell starts with `%%lamb`, then the rest of the cell will be interpreted as a series of definitions in the Lambda Notebook Metalanguage (LNM). Magic cells can also have a return value, and in the lambda notebook this is typically used to display a formatted version of lambda notebook objects in a way that will be familiar to linguists; the `%%lamb` cell magic causes the cell to display any lexical items defined in the cell. The metalanguage is documented in [Metalanguage documentation.ipynb](/notebooks/documentation/Metalanguage documentation.ipynb), and the quick-reference at [Quick reference.ipynb](/notebooks/documentation/Quick reference.ipynb) may also be quite useful.\n", "\n", "For example, the following cell illustrates how you can define some basic lexical entries in the metalanguage:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%lamb\n", "||every|| = lambda f_ : lambda g_ : Forall x_e : f(x) >> g(x)\n", "||cat|| = lambda x_e : Cat_(x)\n", "||dance|| = lambda x_e : Dance_(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Each of these lexical entries provides a name for the entry and a metalanguage expression (in particular, a lambda expression) characterizing the value of the entry. These expressions are parsed and converted to structured metalanguage objects that are stored in the lexicon for future use. Lexical entries defined this way are available by name in following python code cells, e.g. `every` will now access the lambda function defined above. The python `*` operator when used on metalanguage objects performs semantic composition in the sense you may know from linguistic semantics, and the three above lexical entries can be composed as follows in a regular python code cell:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "(every * cat) * dance" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `*` operator here, which is normally the python operator for multiplication, is \"overloaded\" to do composition on lexical items (and their results), returning an object that stores composition results. The following cell illustrates one way you can probe further into a composition result, showing all composition steps that led to the result(s)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "result = (every * cat) * dance\n", "result.tree()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this case, there is one fairly straightforward composition path. A `CompositionResult` object can be manipulated in various ways; for example, the next cell exemplifies how to access the metalanguage object itself that results from composing these items.\n", "\n", "**Important catch in understanding how Jupyter runs code**: the output of a computation can be saved independently of the code generating the actual computation. Running the above `%%lamb` cell defines some lexical items, and as a result renders and displays a piece of the lexicon -- but if you save the notebook and reload, the output will remain without the underlying lexical items being defined. The following cell relies on the `result` variable defined in the previous cell. When you reload a notebook, be sure to run all necessary cells. Keep this principle in mind also when running cells out of order." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "result[0].content" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Unsuccessful composition can also be examined; for example, here is the result of trying to further compose with a property, which leads to no succesful composition paths. The result of every failed composition attempt is shown, including operations that are not FA." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "((every * cat) * dance) * dance" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Line magics:** The lambda notebook also supports several \"line magics\", which can be mixed in with python code inside a cell. This is indicated by a single `%` command at the beginning of a line. The `%lamb` magic can be used as a line magic. In addition, a single expression can be displayed using the `%te` line magic (standing for typed expression). Note that `%te` magics will only display output if they are the last thing in a cell." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%lamb ||dog|| = L x_e : Dog_(x)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%te (L f_ : L x_e : f(x))(L y_e : Dog_(y))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A `%te` object is not simplified by default, but this can be triggered explicitly; in this case it results in beta reduction as much as possible:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%te simplify (L f_ : L x_e : f(x))(L y_e : Dog_(y))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The result of `%te` is a metalanguage object that can be assigned to a python variable and manipulated in many interesting ways:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = %te simplify (L f_ : L x_e : f(x))(L y_e : Dog_(y))\n", "# show x itself, x's type, the righthand part of x, and the simplification steps that resulted in x\n", "display(x, x.type, x[1], x.derivation.trace())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The metalanguage parser can also be accessed in python mode via the function `te` by providing a string argument." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "te(\"(L f_ : L x_e : f(x))(L y_e : Dog_(y))\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Please see the notebook [Lambda Notebook Demo.ipynb](http:///notebooks/Lambda%20Notebook%20Demo.ipynb) for many more examples of how to use these two modes. Two reasonably detailed examples of full, research-oriented fragments can be found in [fragments/Continuations and quantifier scope.ipynb](http:///notebooks/fragments/Continuations%20and%20quantifier%20scope.ipynb) and in [fragments/Variable free binding.ipynb](http:///notebooks/fragments/Variable%20free%20binding.ipynb). A good starting point for understanding and extending the lambda notebook is [tutorials/Type shifting.ipynb](http:///notebooks/tutorials/Type%20shifting.ipynb), which goes through the process of adding a variety of type-shifting operations to a compositional system. Many further examples of various things you might want to do are provided as well, and we welcome contributions.\n", "\n", "These documentation cells are in another mode where you can write ['markdown'-formatted](http://daringfireball.net/projects/markdown/) text; this mode can be chosen from the dropdown box in the toolbar. Also, Jupyter uses the MathJax library to support latex math mode; most equations can be written simply be wrapping them in dollar signs. For example: '$\\lambda x : x \\in D_e \\:.\\: x\\text{ is a cat}$'. To see what the markdown looks like in this notebook, just double-click on any of the text cells (or hit enter with the cell selected). To re-render it, hit shift-enter." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Overview of key features\n", "\n", "This is a non-exhaustive list of features that are available in the lambda notebook.\n", "\n", "Metalanguage and types:\n", "\n", " * lambda calculus, beta reduction, type inference and checking\n", " * polymorphic types\n", " * first-order predicate logic\n", " * set theory\n", " * type domains, evaluation on a model\n", "\n", "Object language interpretation:\n", "\n", " * lexical entries, representations for composed object language\n", " * composition operations on object language elements, including the ability to add new ones\n", " * detailed display of compositional derivations\n", " * multiple composition paths\n", " * (last-resort) type shifting, ability to add new type shifts\n", " * bottom-up composition, top-down composition operations on tree structures.\n", " * binding and object language variables\n", " * tools for composing with partiality\n", " \n", "Some things that are prominently missing:\n", "\n", " * More realistic implementations of presupposition projection.\n", " * Transformations on syntactic representations, for e.g. QR. (You can do QR now, you just have to manually construct the LFs.)\n", " * Integration with a theorem prover\n", " * Integration with any parsing of natural language. (E.g., compare the web demo of boxer.)\n", " \n", "Contributions are welcome!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## More interface notes on jupyter\n", "\n", "The Lambda Notebook is based heavily on the Jupyter Notebook and most of the interface you are seeing is Jupyter. While it may be possible to load some lambda notebook documents in a third-party editor like VSCode, not all features are supported, and so it is highly recommended to use Jupyter itself (e.g., jupyter lab). Here are a few more notes on what exactly Jupyter is that may be helpful if you are new to it.\n", "\n", " * IPython/Jupyter is an enhanced interface (primarily) to python; one of the main targets is interfacing with the 'scipy stack', for doing scientific and mathematical computing. It also provides good support for distributed computing. There is [lots of documentation](https://docs.jupyter.org/en/latest/) and tutorials available.\n", " * Jupyter lab (as well as the classic notebook editor) runs as a \"server\" that is running on your computer and by default only accessible from your local computer. You then select and edit notebooks via a web browser that contacts this server. Typically it runs at the URL [http://localhost:8888](http://localhost:8888). You would typically start this server in a terminal/console window via `jupyter lab`, and can stop it by hitting ctrl-c twice.\n", " * Every loaded notebook corresponds to both a document and a 'kernel' which runs the code on the server. If you close a document by closing the browser window, by default the kernel will still be running and can be shut down (or re-accessed) at the notebook browser. Kernels store program state of any code executed in cells.\n", " * The default location for files is the directory where you start the notebook from, and no directories higher in the filesystem will be accessible.\n", " * Jupyter notebooks can be specified to run under different \"kernels\", which essentially describe the programming language they depend on. The default kernel is just a python kernel; the lambda notebook uses a specialized kernel that loads python and also lambda notebook infrastructure. Example notebooks supplied with this project (e.g., fragments) need this kernel in order to work correctly -- they will not run on the default kernel. However, if you would like a regular python project to load this infrastructure, you can alternatively add `import lamb.auto` to the beginning of the notebook. This is fully equivalent to loading the lambda notebook kernel." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Lambda Notebook (Python 3)", "language": "python", "name": "lambda-notebook" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3" } }, "nbformat": 4, "nbformat_minor": 4 }