- Research Article
5
- 10.1016/s0022-0000(71)80039-9
Subrecursive programming languages II on program size
- Jun 01, 1971
- Journal of Computer and System Sciences
- Robert L Constable
Subrecursive programming languages II on program size
This paper was inspired by [FBW 94]. An arbitrary upper bound on the size of some program for the target function suffices for the learning of some program for this function. In [FBW 94] it was discovered that if “learning” is understood as “identification in the limit,” then in some programming languages it is possible to learn a program of size not exceeding the bound, while in some other programming languages this is not possible.We have studied three other learning types, namely, “finite identification,” “co-learning” and “confidence-learning.” These three types are very different. Co-learning with the considered additional information in the form “an arbitrary upper bound for the size of the minimal program” allows the learning of the class of all recursive functions. “Finite identification” does not allow this. “Confidence-learning” is strong enough to learn the class of all recursive functions even without the additional information. However, the results of our paper show exactly the opposite rating for the capabilities of learning programs not exceeding the size given by the bound.For finite identification it is still possible to identify small programs with additional information in some programming languages but not in all of them. For co-learning it is not possible in any programming language. These results contrast to the result in [FKS 94] showing that an arbitrary class of recursive functions is co-learnable if and only if it is identifiable in the limit. Finally, for confidence-learning it is in general not possible to identify small programs with additional information.KeywordsProgramming LanguageTarget FunctionRecursive FunctionInductive InferenceIdentification TypeThese keywords were added by machine and not by the authors. This process is experimental and the keywords may be updated as the learning algorithm improves.
Subrecursive programming languages II on program size
Subrecursive programming languages II on program size
Efficient compilation of linear recursive functions into object level loops
Whilst widely recognised as an excellent means for solving problems and for designing software, functional programming languages have suffered from their inefficient implementations on conventional computers. A route to improved runtime performance is to transform recursively defined functions into programs which execute more quickly and/or consume less space. We derive equivalent imperative programming language loops for a large class of linear recursive functions of which the tail-recursive functions form a very small subset. We first identify a small set of primitive function defining expressions for which we determine the corresponding loop-expressions. We then determine the loop-expressions for linear functions defined by any expressions which are formed from those primitives. In this way, a very general class of linear functions can be transformed automatically into loops in the parsing phase of a compiler, since the parser has in any case to determine the hierarchical structure of function definitions. Further transformation may involve specific properties of particular defining expressions, and adopt previous schemes. In addition, equivalent linear functions can be found for many non-linear ones which can therefore also be transformed into loops.
Read moreCo-Contextual Type Systems: Contextless Deductive Reasoning for Correct Incremental Type Checking
This thesis proposes a novel way of performing type checking, whose results are incremental, depending on the provided local information. This new way of type checking is called co-contextual, where all context information of expressions, methods, classes, etc., is removed. Instead, we introduce corresponding structures using requirements. Standard type systems are translated to the co-contextual ones systematically using dualism as technique. Type systems play an important role to prevent execution errors from occurring during runtime. They are used to check programs statically for potential errors. Programs are type checked against a given set of rules. Depending on these rules programs are well-typed or not. The set of these rules is called typing rules. Each type rule associates types to the constructs of a program given a certain context. There can be different forms of contexts, depending on the features of the typed programming language. Functional languages use a typing context of variables and their types; object-oriented (OO) languages use additional class tables. Class tables are used for example to ensure that method and class declarations are well-typed. Type checking is performed top-down. While traversing the syntax tree of a program, typing contexts are extended with information on the expressions and their types. In case of OO, class tables are extended with clauses from class declarations, including the class members, i.e., fields, methods, or constructors. Contexts are passed through the nodes of the syntax tree in order to coordinate type checking between them. Therefore, while traversing the syntax tree top-down, the type checker creates dependencies between otherwise independent subexpressions. This way, it inhibits incrementalization and parallelization of type checking. That is, a change to a node of the syntax tree would require to redo the type check of the whole syntax tree. In this thesis a novel formulation of type systems is proposed, in order to remove dependencies between subexpressions. We propose a co-contextual formulation of typing rules that depends only on the local program constructs, e.g., expressions, methods, classes. The co-contextual typing rules have as conclusion a type and sets of requirements. That is, contexts and class tables are replaced by the dual concept of context and class table requirements. In addition, operations on contexts and class tables are replaced by new dual operations on requirements. The co-contextual type checker traverses a syntax tree bottom-up and merges context requirements of independently checked subexpressions. We describe a method for systematically constructing a co-contextual formulation of type rules from a regular context-based formulation and we show how co-contextual type rules give rise to incremental type checking. We derive co-contextual type checkers for functional and OO languages. As a representative of functional languages we consider PCF and extensions of it: records, parametric polymorphism, structural subtyping and let-polymorphism. Also, we investigate featherweight java (FJ) as the basis of OO languages and extensions of it: method overloading and generics. We build a1 co-contextual type checker for FJ enabling key features of OO languages: subtype polymorphism, nominal typing and implementation inheritance. The dualism between the co-contextual and contextual type systems preserves the correctness of the contextual calculus. That is, we prove the correctness of the co-contextual calculus via the equivalence between contextual type rules and their co-contextual formulations. We implemented an incremental type checker for PCF along with a performance evaluation showing that co-contextual type checking has performance comparable to standard context-based type checking, and incrementalization can improve performance significantly. Regarding FJ, we implemented a co-contextual type checker with incrementalization and compared its performance against javac on a number of realistic programs. Our performance evaluation shows significant speedups for the co-contextual type checker with incrementalization in comparison to javac.
Read moreDatabases and Programming
The 1990s saw a hugely productive interaction between database and programming language research. Ideas about type systems from programming languages played a central role in generalizing and adapting relational database systems to new data models. At the same time databases provided some of the best concrete examples of the application of concurrency theory and of the benefits of high-level optimization in functional programming languages. One of the driving ambitions behind this research was the idea that database access should be properly embedded in programming languages: one should not have to be bilingual in order to use a database from a programming language; and that goal has to some extent been realized. In the past fifteen years, new data models, both for data storage and for data exchange have appeared with depressing regularity and with each such model, the inevitable query language. Does programming language research have anything to contribute to these new languages? Should we take the time to to worry about embedding these models in conventional languages? Over the same period, some interesting new connections between databases and programming languages have emerged, notably in the areas of scientific databases, annotation and provenance. Will this provide new opportunities for cross-fertilization?
Read moreOn the size of programs in subrecursive formalisms
This paper gives an overview of subrecursive hierarchy theory as it relates to computational complexity and applies some of the concepts to questions about the size of programs in subrecursive programming languages. The purpose is three-fold, to reveal in simple terms the workings of subrecursive hierarchies, to indicate new results in the area, and to point out ways that the fundamental ideas in hierarchy theory can lead to interesting questions about programming languages. A specific application yields new information about Blum's results on the size of programs and about the relationship between size and efficiency.
Read moreExistence and uniqueness of solution to the problem of determining source term in a semilinear wave equation
The problem of determining source term in a semilinear wave equation is considered. The source term is represented as the product ƒ(u(x, t))p(x), where ƒ(s) is a given function, u(x, t) is a solution to Cauchy problem for wave equation, p(x) is an unknown function. To determine p(x) the additional information on the solution of the Cauchy problem u(α(t), t) = g(t), u(β(t), t) = h(t) is used. Theorems of existence and uniqueness of solution to an inverse problem in the class of continuous functions p(x) and in the class of functions p(x) = po + xq(x), where q(x) is continuous, are proved.
Read moreExistence and uniqueness of solution to the problem of determining source term in a semilinear wave equation
The problem of determining source term in a semilinear wave equation is considered. The source term is represented as the product ƒ(u(x, t))p(x), where ƒ(s) is a given function, u(x, t) is a solution to Cauchy problem for wave equation, p(x) is an unknown function. To determine p(x) the additional information on the solution of the Cauchy problem u(α(t), t) = g(t), u(β(t), t) = h(t) is used. Theorems of existence and uniqueness of solution to an inverse problem in the class of continuous functions p(x) and in the class of functions p(x) = po + xq(x), where q(x) is continuous, are proved.
Read moreArtificial Intelligence in the American Healthcare Industry: Looking Forward to 2030
Artificial Intelligence in the American Healthcare Industry: Looking Forward to 2030
Ct
I will discuss the design of Ct, an API for nested data parallel programming in C++. Ct uses meta-programming and functional language ideas to essentially embed a pure functional programming language in impure and unsafe languages, like C++. I will discuss the evolution of the design into functional programming ideas, how this was received in the corporate world, and how we plan to proliferate the technology in the next year.Ct is a deterministic parallel programming model integrating the nested data parallelism ideas of Blelloch and bulk synchronous processing ideas of Valiant. That is, data races are not possible in Ct. Moreover, performance in Ct is relatively predictable. At its inception, Ct was conceived as a simple library implementation behind C++ template magic. However, performance issues quickly forced us to consider some form of compilation. Using template programming was highly undesirable for this purpose as it would have been difficult and overly specific to C++ idiosyncrasies. Moreover, once compilation for performance was considered, we began to consider a language semantics that would enable powerful optimizations like calculational fusion, synchronization barrier elimination, and so on. The end result of this deliberation is an API that exposes a value-oriented, purely functional vector processing language. Additional benefits of this approach are numerous, including the important ability to co-exist within legacy threading programming models (because of the data isolation inherent in the model). We will show how the model applies to a wide range of important (at least by cycle count) applications. Ct targets both shipping multi-core architectures from Intel as well as future announced architectures.The corporate reception to this approach has (pleasantly) surprised us. In the desktop and high-performance computing space, where C, C++, Java, and Fortran are the only programming models people talk about, we have made serious inroads into advocating advanced programming language technologies. The desperate need for productive, scalable, and safe programming languages for multi-core architectures has provided an opening for functional, type-safe languages. We will discuss the struggles of multi-core manufacturers (i.e. Intel) and their software vendors that have created this opening.For Intel, Ct heralds its first serious effort to champion a technology that borrows functional programming technologies from the research community. Though it is a compromise that accommodates the pure in the impure and safe in the unsafe, this is an important opportunity to demonstrate the power of functional programming to the unconverted. We plan to share the technology selectively with partners and collaborators, and will have a fully functional and parallelizing implementation by year's end. At CUFP, we will be prepared to discuss our long term plans in detail.
Read moreAlgorithm Design in Programming Language Education
Nowadays, when algorithms are combined with programming languages, great technological works are emerging. Examples of these works continue to differentiate and increase in military and police systems, agricultural applications, image processing applications, data engineering field, language processing works, and cyber security applications. With the differentiation of the areas of use of algorithms, the programming languages used on these platforms are also changing. Python is an object-oriented and functional modern programming language. It is ideal for beginners due to its readability and ease of use. C# is a simple, modern, object-oriented, and type-safe programming language that combines the high productivity of application development languages with the raw power of C and C++. The Java programming language, on the other hand, shares many features that are common to most programming languages used today. Since it is designed with the structures of C and C++, where their languages are similar, the language is familiar to C and C++ programmers (Lerdorf, 2002; Hejlsberg, 2003; Arnold, 2005; Deitel, 2004; Kelly, 2016; Gavrilović, 2018; Pala, 2019; Chollet, 2021; Chen, 2023).
Read moreA refinement calculus for nondeterministic expressions
This thesis presents a refinement calculus for transforming highly abstract specifications into programs written in a functional programming language. Refinement calculi allow the derivation of a program from a formal specification by a sequence of correctness-preserving transformation steps. Most refinement calculi target imperative programming languages. Functional programming languages are often more expressive than imperative programming languages. This expressive power leads to a reduced gap between the concepts used to express a problem (as a specification) and the concepts used to express its solution (as a program). Thus, a refinement calculus which targets a functional programming language can lead to a simpler development process which produces a final product more quickly. We build a refinement calculus for functional programs by adding specification constructs to a functional language and examining transformations over the resulting language.This thesis complements other work in the area in two major ways. Firstly, we investigate the addition of truly-nondeterministic, rather than underdetermined, choice constructs to a functional language. These constructs allow specifications which are more abstract and which admit more implementations. Secondly, most refinement calculi for functional programs add erratic choice constructs to a functional language. We investigate the addition of both demonic and angelic nondeterminism to a functional language. Demonic and erratic choice are similar: given a number of alternatives, they choose any one. In contrast, given a number of alternatives angelic choice always makes the correct choice, if one exists. Angelic choice is difficult to reason about, but allows the concise specification of powerful parallel constructs.
Read moreFalafel: Arrays in a Functional Language
Falafel, a functional programming language with first-class arrays, is being developed at the University of Saskatchewan. It is an experimental vehicle for work in language definition and implementation. This paper discusses some of the fundamental design decisions that underlie the language and its implementations. Falafel has drawn ideas from array-based programming languages (APL [Iverson] and Nial [Jenkins]_[More]), functional programming languages (Miranda™ [Turner] and Haskell [Haskell]), and dataflow programming languages (Id [Nikhil]_and Sisal [Sisal]). This paper discusses the nature of Falafel’s value space, the structure of arrays, the role of strong polymorphic typing, the use of lazy evaluation, and a means of partial definition of arrays. A full definition of Falafel is to be published separately.
Read moreTyped object-oriented functional programming with late binding
Object-oriented programming languages are suitable for describing real-world objects, functional programming languages for algebraic values. In this paper we propose an object-oriented functional programming language, called TOFL, which combines many desired properties of the two paradigms. In particular, TOFL unifies object classes, inheritance, (method) redefinitions and late binding as in object-oriented languages, algebraic data types, higher-order functions, type classes and type inference (without type reconstruction in this paper) as in functional languages. We translate TOFL into a stratified and explicitly typed λ-calculus T with overloaded functions, where redefinitions and late binding become late binding of overloaded functions. The operational semantics of T gives a semantics and a simple prototyping implementation of TOFL.
Read moreVerification by Reduction to Functional Programs
In this thesis, we explore techniques for the development and verification of programs in a high-level, expressive, and safe programming language. Our programs can express problems over unbounded domains and over recursive and mutable data structures. We present an implementation language flexible enough to build interesting and useful systems. We mostly maintain a core shared language for the specifications and the implementation, with only a few extensions specific to expressing the specifications. Extensions of the core shared language include imperative features with state and side effects, which help when implementing efficient systems. Our language is a subset of the Scala programming language. Once verified, programs can be compiled and executed using the existing Scala tools. We present algorithms for verifying programs written in this language. We take a layer-based approach, where we reduce, at each step, the program to an equivalent program in a simpler language. We first purify functions by transforming away mutations into explicit return types in the functions' signatures. This step rewrites all mutations of data structures into cloning operations. We then translate local state into a purely functional code, hence eliminating all traces of imperative programming. The final language is a functional subset of Scala, on which we apply verification. We integrate our pipeline of translations into Leon, a verifier for Scala. We verify the core functional language by using an algorithm already developed inside Leon. The program is encoded into equivalent first-order logic formulas over a combination of theories and recursive functions. The formulas are eventually discharged to an external SMT solver. We extend this core language and the solving algorithm with support for both infinite-precision integers and bit-vectors. The algorithm takes into account the semantics gap between the two domains, and the programmer is ultimately responsible to use the proper type to represent the data. We build a reusable interface for SMT-LIB that enables us to swap solvers transparently in order to validate the formulas emitted by Leon. We experiment with writing solvers in Scala; they could offer both a better and safer integration with the rest of the system. We evaluate the cost of using a higher-order language to implement such solvers, traditionally written in C/C++. Finally, we experiment with the system by building fully working and verified applications. We rely on the intersection of many features including higher-order functions, mutable data structures, recursive functions, and nondeterministic environment dependencies, to build concise and verified applications.
Read morePromoting rewriting to a programming language: a compiler for non-deterministic rewrite programs in associative-commutative theories
First-order languages based on rewrite rules share many features with functional languages, but one difference is that matching and rewriting can be made much more expressive and powerful by incorp...
Read more