We use cookies to distinguish you from other users and to provide you with a better experience on our websites. Close this message to accept cookies or find out how to manage your cookie settings.
To save content items to your account,
please confirm that you agree to abide by our usage policies.
If this is the first time you use this feature, you will be asked to authorise Cambridge Core to connect with your account.
Find out more about saving content to .
To save content items to your Kindle, first ensure [email protected]
is added to your Approved Personal Document E-mail List under your Personal Document Settings
on the Manage Your Content and Devices page of your Amazon account. Then enter the ‘name’ part
of your Kindle email address below.
Find out more about saving to your Kindle.
Note you can select to save to either the @free.kindle.com or @kindle.com variations.
‘@free.kindle.com’ emails are free but can only be saved to your device when it is connected to wi-fi.
‘@kindle.com’ emails can be delivered even when you are not connected to wi-fi, but note that service fees apply.
We have presented sample λProlog programs to illustrate various computations throughout this book. Being able to execute and experiment with those programs should help the reader understand the λProlog programming language and the logic underlying it. To that end, this appendix presents a short introduction to the Teyjus implementation of λProlog. This system can be freely downloaded over the web. The various programs presented in the earlier chapters are also available in electronic form from the website associated with this book.
An overview of the Teyjus system
The Teyjus implementation of λProlog is based on two components. One component is the emulator of an abstract or virtual machine that has an instruction set and runtime system that realizes all the high-level computations implicit in a λProlog program. The second component is a compiler that translates λProlog programs into the instructions of the abstract machine.
Another important aspect of the Teyjus system is that it uses the modules language discussed in Chapter 6. A programmer therefore, must, organize the kind and type declarations and the clauses into modules and then attach signatures to such modules in order to mediate their external view. The compiler is responsible for taking a given module of λProlog code, certifying its internal consistency, ensuring that it satisfies its associated signature, and finally, translating it into a byte-code form. This byte-code form consists of a “header” part containing constant and type names and other related data structures as well as a sequence of instructions that can be run on the virtual machine once it has understood the header information. A critical part of the emulator is a loader that can read in such byte-code files and put the emulator in a state where it is ready to respond to user queries. The other part of the emulator is, of course, a byte-code interpreter that steps through instructions in the manner called for by the user input.
Chapter 1 discussed the use of first-order terms to represent data. This chapter describes logic programming over such representations using a typed variant of first-order Horn clauses. We begin this presentation by developing a view of logic programming that will allow us to introduce extensions smoothly in later chapters, leading eventually to the full set of logical features that underlie the λProlog language. From this perspective, we will take this paradigm of programming to have two defining characteristics. First, languages within the paradigm provide a relational approach to programming. In particular, relations over data descriptions are defined or axiomatized through formulas that use logical connectives and quantifiers. Second, the paradigm views computation as a search process. In the approach underlying λProlog, this view is realized by according to each logical symbol a fixed search-related interpretation. These interpretations lead, in turn, to specific programming capabilities.
The first two sections that follow provide a more detailed exposition of a general framework for logic programming along the lines just sketched. The rest of the chapter is devoted to presenting first-order Horn clauses as a specific elaboration of this framework.
First-order formulas
The first step toward allowing for the description of relations over objects represented by first-order terms is to ease a restriction on signatures: We permit the target types of constants to be ο. Constants that have this type are called relation or predicate symbols. Well-formed first-order expressions are otherwise constructed in the same fashion as that described in Section 1.3. Expressions that have the type ο in this setting are referred to as first-order atomic formulas.
Formal systems in computer science frequently involve specifications of computations over syntactic structures such as λ-terms, π-calculus expressions, first-order formulas, types, and proofs. This book is concerned, in part, with using higher-order logic to express such specifications. Properties are often associated with expressions by formal systems via syntax-based inference rules. Examples of such descriptions include presentations of typing and operational semantics. Logic programming, with its orientation around rule-based specifications, provides a natural framework for encoding and animating these kinds of descriptions. Variable binding is integral to most syntactic expressions, and its presence typically translates into side conditions accompanying inference rules. While many of the concepts related to binding, such as variable renaming, substitution, and scoping, are logically well understood, their treatment at a programming level is surprisingly difficult. We show here that a programming language based on a simply typed version of higher-order logic provides an elegant approach to performing computations over structures embodying binding.
The agenda just described has a prerequisite: We must be able to make sense of a higher-order logic as a programming language. This is a nontrivial task that defines a second theme that permeates this book. Usual developments of logic programming are oriented around formulas in clausal form with resolution as the sole inference rule. Sometimes a semantics-based presentation is also used, expanding typically into the idea of minimal (Herbrand) models.
This chapter considers the encoding of a process calculus within a higher-order logic programming language. Process calculi have been proposed in the literature as a means for modeling concurrent systems. The π-calculus in particular makes use of a sophisticated binding mechanism to encode communication between processes. Our goal here is to show that such binding mechanisms can be treated naturally using λ-tree syntax in λProlog. Since we do not discuss the π-calculus itself in any detail, a reader probably would need a prior exposure to this calculus to best appreciate the nuances of our encodings. However, our primary focus is on showing how a presentation of a formal system can be transformed into a complete and logically precise description in λProlog and how such a description can be used computationally. Thus a reader who has understood the earlier chapters also should be able to follow our development and perhaps will learn something about the π-calculus from it.
The first two sections of this chapter describe an abstract syntax representation for processes in the π-calculus and the specification of the standard transition relation over such processes. A highlight of this specification is that the transition rules are encoded in a completely logical fashion through the use of λ-tree syntax: The usual side conditions involving names are captured completely using binders and their mobility. Sections 11.3 and 11.4 discuss how our encoding can be used in analyzing computational behavior. This discussion also illuminates shortcomings of the logic programming setting in specifying what is known as the must behavior of processes. The last section further illustrates our approach to abstract syntax by showing the translation of a mapping of the λ -calculus under a call-by-name evaluation semantics into the π -calculus.
The previous chapters have dealt with logic programming in the context of first-order logic. We are now interested in moving the discussion to the setting of a higher-order logic. The particular logic that we will use for this purpose is one based on the simply typed λ-calculus, generalized to allow for a form of polymorphic typing. This underlying calculus has several nontrivial computational characteristics that themselves merit discussion. We undertake this task in this chapter, delaying the presentation of the higher-order logic and the logic programming language based on it until Chapter 5.
The first two sections of this chapter describe the syntax of the simply typed λ-calculus and an equality relation called λ-conversion that endows the expressions of this calculus with a notion of functionality. The λ-conversion operation brings with it considerable computational power. We discuss this aspect in Section 4.3. In the logic programming setting, λ-conversion will not be deployed directly as a computational device but instead will be used indirectly in the course of solving unification problems between λ-terms. A discussion of this kind of unification, commonly called higher-order unification, is the focus of the second half of this chapter. Section 4.4 presents a general format for such problems, introduces terminology relating to them, and tries to develop intuitions about the solutions to these problems. Section 4.5 begins to develop the structure for a procedure that might be used to solve higher-order unification problems; this discussion is incomplete and meant only as a prelude to the more detailed treatment of higher-order unification that appears in Chapter 8.
The treatment of programs as objects is a theme common to systems such as interpreters, compilers, and program transformers. These systems typically use an abstract representation of programs that they then manipulate in accordance with the syntax-directed operational semantics of the underlying programming language. The λProlog language can capture such representation and manipulation of programs in a succinct and declarative manner. We illustrate this strength of λProlog by considering various computations over programs in a simple but representative functional language. In the first section we describe this language through its λ-tree syntax; we assume that the reader is sufficiently familiar with functional programming notions to be able to visualize a corresponding concrete syntax. In Section 10.2we present two different specifications of evaluation with respect to this language. In Section 10.3 we consider the encoding of some transformations on programs that are driven by an analysis of their syntactic structure.
The miniFP programming language
The functional programming language that we use in this illustration is called miniFP. While miniFP is a typed language, in its encoding we initially treat its programs as being untyped: We later introduce a language of types and consider a program to be proper only if a type can be associated with it.
The core of the language of program expressions, then, is the untyped λ-calculus. We use the type tm for these expressions, and we encode them in the manner described in Section 7.1.2 for this calculus, with the difference that we use the symbol @ instead of app to represent the application of two expressions, and we write @ as an infix operator.
Provides an innovative hands-on introduction to techniques for specifying the behaviour of software components. It is primarily intended for use as a text book for a course in the 2nd or 3rd year of Computer Science and Computer Engineering programs, but it is also suitable for self-study. Using this book will help the reader improve programming skills and gain a sound foundation and motivation for subsequent courses in advanced algorithms and data structures, software design, formal methods, compilers, programming languages, and theory. The presentation is based on numerous examples and case studies appropriate to the level of programming expertise of the intended readership. The main topics covered are techniques for using programmer-friendly assertional notations to specify, develop, and verify small but non-trivial algorithms and data representations, and the use of state diagrams, grammars, and regular expressions to specify and develop recognizers for formal languages.
A no-nonsense introduction to software design using the Python programming language. Written for people with no programming experience, this book starts with the most basic concepts and gradually adds new material. Some of the ideas students find most challenging, like recursion and object-oriented programming, are divided into a sequence of smaller steps and introduced over the course of several chapters. The focus is on the programming process, with special emphasis on debugging. The book includes a wide range of exercises, from short examples to substantial projects, so that students have ample opportunity to practise each new concept. Exercise solutions and code examples are available from thinkpython.com, along with Swampy, a suite of Python programs that is used in some of the exercises.
This new, expanded textbook describes all phases of a modern compiler: lexical analysis, parsing, abstract syntax, semantic actions, intermediate representations, instruction selection via tree matching, dataflow analysis, graph-coloring register allocation, and runtime systems. It includes good coverage of current techniques in code generation and register allocation, as well as functional and object-oriented languages, that are missing from most books. In addition, more advanced chapters are now included so that it can be used as the basis for two-semester or graduate course. The most accepted and successful techniques are described in a concise way, rather than as an exhaustive catalog of every possible variant. Detailed descriptions of the interfaces between modules of a compiler are illustrated with actual C header files. The first part of the book, Fundamentals of Compilation, is suitable for a one-semester first course in compiler design. The second part, Advanced Topics, which includes the advanced chapters, covers the compilation of object-oriented and functional languages, garbage collection, loop optimizations, SSA form, loop scheduling, and optimization for cache-memory hierarchies.
The new edition of this successful and established textbook retains its two original intentions of explaining how to program in the ML language, and teaching the fundamentals of functional programming. The major change is the early and prominent coverage of modules, which are extensively used throughout. In addition, the first chapter has been totally rewritten to make the book more accessible to those without experience of programming languages. The main features of new Standard Library for the revised version of ML are described and many new examples are given, while references have also been updated. Dr Paulson has extensive practical experience of ML and has stressed its use as a tool for software engineering; the book contains many useful pieces of code, which are freely available (via the Internet) from the author. He shows how to use lists, trees, higher-order functions and infinite data structures. Many illustrative and practical examples are included.. Efficient functional implementations of arrays, queues, priority queues, etc. are described. Larger examples include a general top-down parser, a lambda-calculus reducer and a theorem prover. The combination of careful explanation and practical advice will ensure that this textbook continues to be the preferred text for many courses on ML.
This introduction to the basic ideas of structural proof theory contains a thorough discussion and comparison of various types of formalization of first-order logic. Examples are given of several areas of application, namely: the metamathematics of pure first-order logic (intuitionistic as well as classical); the theory of logic programming; category theory; modal logic; linear logic; first-order arithmetic and second-order logic. In each case the aim is to illustrate the methods in relatively simple situations and then apply them elsewhere in much more complex settings. There are numerous exercises throughout the text. In general, the only prerequisite is a standard course in first-order logic, making the book ideal for graduate students and beginning researchers in mathematical logic, theoretical computer science and artificial intelligence. For the new edition, many sections have been rewritten to improve clarity, new sections have been added on cut elimination, and solutions to selected exercises have been included.
Recent years have seen the development of powerful tools for verifying hardware and software systems, as companies worldwide realise the need for improved means of validating their products. There is increasing demand for training in basic methods in formal reasoning so that students can gain proficiency in logic-based verification methods. The second edition of this successful textbook addresses both those requirements, by continuing to provide a clear introduction to formal reasoning which is both relevant to the needs of modern computer science and rigorous enough for practical application. Improvements to the first edition have been made throughout, with extra and expanded sections on SAT solvers, existential/universal second-order logic, micro-models, programming by contract and total correctness. The coverage of model-checking has been substantially updated. Further exercises have been added. Internet support for the book includes worked solutions for all exercises for teachers, and model solutions to some exercises for students.
The Internet and World Wide Web have revolutionized access to information. Users now store information across multiple platforms from personal computers to smartphones and websites. As a consequence, data management concepts, methods and techniques are increasingly focused on distribution concerns. Now that information largely resides in the network, so do the tools that process this information. This book explains the foundations of XML with a focus on data distribution. It covers the many facets of distributed data management on the Web, such as description logics, that are already emerging in today's data integration applications and herald tomorrow's semantic Web. It also introduces the machinery used to manipulate the unprecedented amount of data collected on the Web. Several 'Putting into Practice' chapters describe detailed practical applications of the technologies and techniques. The book will serve as an introduction to the new, global, information systems for Web professionals and master's level courses.
This textbook is an introduction to denotational semantics and its applications to programming languages. Dr Allison emphasizes a practical approach and the student is encouraged to write and test denotational definitions. The first section is devoted to the mathematical foundations of the subject and sufficient detail is given to illustrate the fundamental problems. The remainder of the book covers the use of denotational semantics to describe sequential programming languages such as Algol, Pascal and C. Throughout, numerous exercises, usually in Pascal, will help the student practise writing definitions and carry out simple applications. The book culminates in discussing an executable semantics of the logic-programming language Prolog. Being an introduction, advanced undergraduates in computer science and graduates new to the subject will find this a readily accessible account of one of the central topics of computer science.
This concise introduction to model theory begins with standard notions and takes the reader through to more advanced topics such as stability, simplicity and Hrushovski constructions. The authors introduce the classic results, as well as more recent developments in this vibrant area of mathematical logic. Concrete mathematical examples are included throughout to make the concepts easier to follow. The book also contains over 200 exercises, many with solutions, making the book a useful resource for graduate students as well as researchers.
This is an introduction to programming using Microsoft's Visual Basic.NET 2010, intended for novice programmers with little or no programming experience or no experience with Visual Basic. The text emphasizes programming logic and good programming techniques with generous explanations of programming concepts written from a non-technical point of view. It stresses input, processing, and output and sequence, selection, and repetition in code development. File I/O and arrays are included. Later chapters introduce objects, event programming, and databases. By taking a slow and steady approach to programming ideas, this book builds new concepts from what the reader has already learned. VB tips and quips inject both humor and insight. The book includes numerous programming examples and exercises, case studies, tutorials, and 'fixing a program' sections for an in-depth look at programming problems and tools. Quizzes and review questions throughout each chapter get students to think about the materials and how to use them. Each chapter has a summary and glossary for extra review. The accompanying website, www.cambridge.org/us/McKeown, has code downloads, I/O, and database files from small, simple files to large files with thousands of records, flowcharts, deskchecks and audits to aid with program design, coding, and debugging; PowerPoint files for every chapter; and hundreds of ideas for programs and projects.
This textbook offers a unified and self-contained introduction to the field of term rewriting. It covers all the basic material (abstract reduction systems, termination, confluence, completion, and combination problems), but also some important and closely connected subjects: universal algebra, unification theory, Gröbner bases and Buchberger's algorithm. The main algorithms are presented both informally and as programs in the functional language Standard ML (an appendix contains a quick and easy introduction to ML). Certain crucial algorithms like unification and congruence closure are covered in more depth and Pascal programs are developed. The book contains many examples and over 170 exercises. This text is also an ideal reference book for professional researchers: results that have been spread over many conference and journal articles are collected together in a unified notation, proofs of almost all theorems are provided, and each chapter closes with a guide to the literature.
Domain theory is an established part of theoretical computer science, used in giving semantics to programming languages and logics. In mathematics and logic it has also proved to be useful in the study of algorithms. This book is devoted to providing a unified and self-contained treatment of the subject. The theory is presented in a mathematically precise manner which nevertheless is accessible to mathematicians and computer scientists alike. The authors begin with the basic theory including domain equations, various domain representations and universal domains. They then proceed to more specialized topics such as effective and power domains, models of lambda-calculus and so on. In particular, the connections with ultrametric spaces and the Kleene–Kreisel continuous functionals are made precise. Consequently the text will be useful as an introductory textbook (earlier versions have been class-tested in Uppsala, Gothenburg, Passau, Munich and Swansea), or as a general reference for professionals in computer science and logic.