
John Launchbury- Galois Inc.
John Launchbury
- Galois Inc.
About
89
Publications
17,019
Reads
How we measure 'reads'
A 'read' is counted each time someone views a publication summary (such as the title, abstract, and list of authors), clicks on a figure, or views or downloads the full-text. Learn more
2,750
Citations
Introduction
Skills and Expertise
Current institution
Publications
Publications (89)
Ivory is a language that enforces memory safety and avoids most undefined behaviors while providing low-level control of memory-manipulation. Ivory is embedded in a modern variant of Haskell, as implemented by the GHC compiler. The main contributions of the paper are twofold. First, we demonstrate how to embed the type-system of a safe-C language i...
We report on our experiences in synthesizing a fully-featured autopilot from embedded domain-specific languages (EDSLs) hosted in Haskell. The autopilot is approximately 50k lines of C code generated from 10k lines of EDSL code and includes control laws, mode logic, encrypted communications system, and device drivers. The autopilot was built in les...
We report on our experiences in synthesizing a fully-featured autopilot from embedded domain-specific languages (EDSLs) hosted in Haskell. The autopilot is approximately 50k lines of C code generated from 10k lines of EDSL code and includes control laws, mode logic, encrypted communications system, and device drivers. The autopilot was built in les...
We briefly describe the use of embedded domain-specific languages to improve programmer productivity and increase software assurance in the context of building a fully-featured autopilot for unpiloted aircraft.
Fold functions are a general mechanism for computing over recursive data
structures. First-order folds compute results bottom-up. With higher-order
folds, computations that inherit attributes from above can also be expressed.
In this paper, we explore folds over a form of recursive higher-order function,
called hyperfunctions, and show that hyperfu...
We describe a method by which language parsers and interpreters may be implemented in a lazy functional programming language. The visual appearance of such interpreters mimics the BNF description of the grammar of the language being interpreted. The method is particularly well suited to the implementation of language interpreters that are based on...
Secure multiparty computation (SMC) permits a collection of parties to compute a collaborative result, without any of the parties gaining any knowledge about the inputs provided by other parties. Specifications for SMC are commonly presented as boolean circuits, where optimizations come mostly from reducing the number of multiply-operations (includ...
Even though step-by-step refinement has long been seen as desirable, it is hard to find compelling industrial applications of the technique. In theory, transforming a high-level specification into a high-performance implementation is an ideal means of producing a correct design, but in practice it is hard to make it work, and even harder to make it...
Network operators must configure networks to accomplish critical, complex, and often conflicting requirements: they must ensure good performance while maintaining security, and satisfy contractual obligations while ensuring profitable use of interdomain connections. Unfortunately, today they have no choice but to implement these high-level goals by...
We present a concurrent scripting language embedded in Haskell, emulating the functionality of the Orc orchestration language by providing many-valued (real) non-determinism in the context of concurrent effects. We provide many examples of its use, as well as a brief description of how we use the embedded Orc DSL in practice. We describe the abstra...
Functional languages have been the backbone of Galois’ business for the past eight years. They have been very good for us,
but not without their own share of challenges. In this talk, we shall stand back and examine the practicalities of using declarative
methods over a range of projects and products, to see what works well in practice, and convers...
Simulations between processes can be understood in terms of coalgebra homomorphisms, with homomorphisms to the final coalgebra
exactly identifying bisimilar processes. The elements of the final coalgebra are thus natural representatives of bisimilarity
classes, and a denotational semantics of processes can be developed in a final-coalgebra- enriche...
At Galois, we use Haskell extensively in a carefully architected DAV server. Our clients need very strong separation between separate network access points. Haskell gave us critical flexibility to provide major pieces of functionality that enable the separation, including the implementation of a completely new file system. Interestingly, however, w...
Program analyses are often presented as one of two brands: forwards or backwards. In this paper we explore the significance of the direction of analysis, and show how arbitrary abstract interpretations may be reversed.
As a company, Galois began its life with the mission simply of supplying functional programming services, building tools and products for clients, leveraging the productivity of functional languages and the abilities of our engineers. This went well, except that our business lacked focus. Every new job had to be found and sold from scratch. We real...
Certain programs making use of monads need to perform recursion over the values of monadic actions. Although the do-notation of Haskell provides a convenient framework for monadic programming, it lacks the generality to support such recursive bindings. In this paper, we describe an enhanced translation schema for the donotation and its integration...
Monads have been employed in programming languages for modeling various language features, most importantly those that involve side effects. In particular, Haskell's IO monad provides access to I/O operations and mutable variables, without compromising referential transparency. Cyclic definitions that involve monadic computations give rise to the c...
Recent work on recursion over the values of monadic actions resulted in the introduction of a family of fixed point operators, one for each di#erent kind of monadic e#ect. In the context of Haskell, the function fixIO is the corresponding operator for the IO monad. Unfortunately, both the IO monad and fixIO are language primitives in Haskell, i.e....
this in [KLP01], where a general construction of coalgebra enriched categories is given, motivated mostly by applications in the semantics of processes. (Categories of resumptions and hyperfunctions are the simplest examples of the construction.) While the semantic relevance and programming potential of hyperfunctions are still unclear, their conce...
Simulations between processes can be understood in terms of coalgebra homomorphisms, with homomorphisms to the final coalgebra exactly identifying bisimilar processes. The elements of the final coalgebra are thus natural representatives of bisimilarity classes, and a denotational semantics of processes can be developed in a final-coalgebra-enriched...
Monads have become a popular tool for dealing with computational effects in Haskell for two significant reasons: equational reasoning is retained even in the presence of effects; and program modularity is enhanced by hiding "plumbing" issues inside the monadic infrastructure. Unfortunately, not all the facilities provided by the underlying language...
We define an operational semantics for lazy evaluation which provides an accurate model for sharing. The only computational structure we introduce is a set of bindings which corresponds closely to a heap. The semantics is set at a considerably higher level of abstraction than operational semantics for particular abstract machines, so is more suitab...
Monads have become a popular tool for dealing with computational e ects in Haskell for two signi- cant reasons: equational reasoning is retained even in the presence of eects ; and program modularity is enhanced by hiding \plumbing" issues inside the monadic infrastructure. Unfortunately, not all the facil- ities provided by the underlying language...
Our general goal is to provide a semantic foundation for the specification of concurrent and distributed object systems. We use Troll, a formal object-oriented language, for system specification. It is now widely accepted that object classes are unsuitable modularisation units when it comes to dealing with very large systems. An intermediate concep...
Introduction In the usual mathematical practice, functions whose arguments are functions are commonplace. Functions whose arguments are functions whose arguments are functions are rarer, and everything beyond the third level is exotic. Innitely nested function spaces like H(A;B) = (((( ! A) ! B) ! A) ! B) cannot exist for cardinality reasons. In do...
Type of Hyperfunctions Now that we have three models that support programming with coroutining continuations, it is natural to ask about the core functionality provided by all of them. So we embark on a study of an abstract type. We give the axiomatics satised by all three models. We establish some connections between the models and obtain some pre...
Based on our experience with modelling and verifying microarchitectural designs within Haskell, this paper examines our use of Haskell as host for an embedded language. In particular we highlight our use of Haskell's lazy lists type classes, lazy state monad, and unsafePerformIO, and point to several areas where Haskell could be improved in the fut...
Graph reduction underlies most implementations of lazy functional languages, allowing separate computations to share results when subterms are evaluated. Once a term is evaluated, the node of the graph representing the computation is updated with the value of the term. However, in many cases, no other computation requires this value, so the update...
Certain programs making use of monads need to perform recursion over the values of monadic actions. Although the do-notation of Haskell provides a convenient framework for monadic programming, it lacks the generality to support such recursive bindings. To remedy this problem, we propose an extension to Haskell's do-notation and describe its transla...
ions in Haskell Nancy A. Day John Launchbury Je Lewis Oregon Graduate Institute of Science & Technology Abstract We describe a generalization of the Haskell Boolean type, which allows us to use existing decision procedures for reasoning about logical expressions. In particular, we have connected Haskell with a Binary Decision Diagram (BDD) package...
This paper introduces a language feature, called implicit parameters, that provides dynamically scoped variables within a statically-typed Hindley-Milner framework. Implicit parameters are lexically distinct from regular identiers, and are bound by a special with construct whose scope is dynamic, rather than static as with let. Implicit parameters...
array :: (Ix a) =? (a,a) -? [(a,b)] -? Array a b listArray :: (Ix a) =? (a,a) -? [b] -? Array a b (!) :: (Ix a) =? Array a b -? a -? b bounds :: (Ix a) =? Array a b -? (a,a) indices :: (Ix a) =? Array a b -? [a] elems :: (Ix a) =? Array a b -? [b] assocs :: (Ix a) =? Array a b -? [(a,b)] accumArray :: (Ix a) =? (b -? c -? b) -? b -? (a,a) -? [(a,c)...
Type safety of imperative programs is an area fraught with difficulty and requiring great care. The SML solution to the problem, originally involving imperative type variables, has been recently simplified to the syntactic-value restriction. In Haskell, the problem is addressed in a rather different way using explicit monadic state. We present an o...
Based on our experience with modelling and verifying microarchitectural designs within Haskell, this paper examines our use of Haskell as host for an embedded language. In particular, we highlight our use of Haskell's lazy lists, type classes, lazy state monad, and unsafe Perform I0, and point to several areas where Haskell could be improved in the...
Microarchitects are increasingly using techniques such as speculation, register renaming, and superscalar out-of-order execution to make use of instruction-level parallelism. However, the growing complexity of modern microprocessors exacerbates the difficulty of relating them to the simple machines that they emulate. Flaws found later in lower-leve...
In functional programming, small programs are often combined to construct larger, more complex ones. The component reuse encouraged by this modular style of programming yields many benefits, but, unfortunately, modular programs also tend to be less efficient than their monolithic counterparts. This is frequently due to the construction of intermedi...
This is a companion note to Elementary Microarchitecture Algebra [1] and outlines an algebraic simplication proof of the pipelined microarchitecture described in that paper. 1 Transforming the Microarchitecture The laws presented in Elementary Microarchitecture Algebra [1], as well as others introduced in this note, can be used for aggressively res...
We describe a set of remarkably simple algebraic laws governing microarchitectural components. We apply these laws to incrementally
transform a pipeline containing forwarding, branch speculation and hazard detection so that all pipeline stages and forwarding
logic are removed. The resulting unpipelined machine is much closer to the reference archit...
We provide a framework for the specification and verification of high-performance processors. As an example, we give a high-level specification and correctness proof for a processor that uses speculation, register renaming, superscalar out-of-order execution, and resolution of memory dependencies. The specifications of its three concurrently operat...
The trend in microprocessor design is to extend instruction-set architectures with features—such as parallelism annotations,
predication, speculative memory access,or multimedia instructions—that allow the compiler or programmer to express more instruction-level
parallelism than the microarchitecture is willing to derive. In this paper we show how...
Extending the -calculus with either explicit substitution or generalized reduction has been the subject of extensive research recently, and still has many open problems. This paper is the first investigation into the properties of a calculus combining both generalized reduction and explicit substitutions. We present a calculus, gs, that combines a...
The code compiled from a non-strict functional program usually manipulates heap-allocated boxed numbers. Compilers for such languages often go to considerable trouble to optimise operations on boxed numbers into simpler operations on their unboxed forms. These optimisations are usually handled in an ad hoc manner in the code generator, because earl...
. Some algorithms make critical internal use of updatable state, even though their external specification is purely functional. Based on earlier work on monads, we present a way of securely encapsulating stateful computations that manipulate multiple, named, mutable objects, in the context of a non-strict, purely-functional language. The security o...
Some algorithms make critical internal use of updatable state, even though their external specification is purely functional. Based on earlier work on monads, we present a way of securely encapsulating such stateful computations, in the context of a non-strict, purely-functional language.
There are two main new developments in this paper. First,...
Depth-first search is the key to a wide variety of graph algorithms. In this paper we explore the implementation of depth first search in a lazy functional language. For the first time in such languages we obtain a linear-time implementation. But we go further. Unlike traditional imperative presentations, algorithms are constructed from individual...
Modern microprocessors require an immense investment of time and effort to create and verify, from the high level architectural design downwards. We are exploring ways to increase the productivity of design engineers by creating a domain specific language for specifying and simulating processor architectures. We believe that the structuring princip...
Hawk is a language for the specification of microprocessors at the microarchitectural level. In this paper we use Hawk to specify a modern microarchitecture based on the Intel P6 with features such as speculation, register renaming, and superscalar out-of-order execution.
We formalize the meaning of lazy memo-functions in Haskell with an extension to the lazy -calculus, Haskell's computational model. The semantics enable reasoning about memoization 's effect on space and time complexity. Based on the semantics, we present a prototype implementation that requires no changes to the garbage-collector; memo-tables are s...
Modern microprocessors require an immense investment of time and effort to create and verify, from the high level architectural design downwards. We are exploring ways to increase the productivity of design engineers by creating a domain specific language for specifying and simulating processor architectures. We believe that the structuring princip...
Domain specific languages are small, special purpose languages created to describe computational solutions in a particular problem domain. Domain specific languages have proven themselves useful many times over; however, the cost of defining and implementing a domain specific language can be high. An approach that avoids the overhead of domain spec...
Program fusion is the process whereby separate pieces of code are fused into a single piece, typically transforming a multi-pass algorithm into a single pass. Recent work has made it clear that the process is especially successful if the loops or recursions are expressed using catamorphisms (e.g.foldr) and constructor-abstraction (e.g. build). In t...
Compilers for ML and Haskell use intermediate languages that incorporate deeply-embedded assumptions about order of evaluation and side effects. We propose an intermediate language into which one can compile both ML and Haskell, thereby facilitating the sharing of ideas and infrastructure, and supporting language developments that move each languag...
We observe that the principal typing property of a type system is the enabling technology for modularity and separate compilation [10]. We use this technology to formulate a modular and polyvariant closure analysis, based on the ...
The projection-based strictness analysis of Wadler and Hughes is elegant and theoretically satisfying except in one respect: the need for lifting. The domains and functions over which the analysis is performed need to be transformed, leading to a less direct correspondence between analysis and program than might be hoped for. In this paper we shall...
. In lazy functional languages, ? is typically an element of every type. While this provides great flexibility, it also comes at a cost. In this paper we explore the consequences of allowing unpointed types in a lazy functional language like Haskell. We use the type (and class) system to keep track of pointedness, and show the consequences for para...
This book presents the eight tutorial lectures given at the Second International School on Advanced Functional Programming, held in Olympia, WA, USA, in August 1996.
After many years of development, functional programming languages have matured to a point where they can be used for much larger applications than has been typical in the past. These t...
Projection-based backwards strictness analysis has been understood for some years. Surprisingly, even though the method is fairly simple and quite general, no reports of its implementation have appeared. This paper describes ideas underlying our prototype implementation of the analysis for a simple programming language. The implementation serves as...
this paper, that results from this kind of analysis are, in a sense, polymorphic. This confirms an earlier conjecture [19], and shows how the technique can be applied to first-order polymorphic functions. The paper is organised as follows. In the next section, we review projection-based strictness analysis very briefly. In Section 3 we introduce th...
Thunk lifting, a program transformation for lazy functional programs, aims to reduce the amount of heap space allocated to the program when it executes. Thunk lifting eliminates nesting of function applications, by folding selected applications. The conditions for selection guarantee that thunk lifting never increases the amount of heap space requi...
Graph algorithms have long been a challenge to program in a pure functional language. Previous attempts have either tended to be unreadable, or have failed to achieve standard asymptotic complexity measures. We explore a number of graph search algorithms in which we achieve standard complexities, while significantly improving upon traditional imper...
Lists are often used as "glue" to connect separate parts of a program together. We propose an automatic technique for improving the efficiency of such programs, by removing many of these intermediate lists, based on a single, simple, local transformation. We have implemented the method in the Glasgow Haskell compiler. 1 Introduction Functional prog...
Performing a depth-first search of a graph is one of the fundamental approaches for solving a variety of graph algorithms. Implementing depthfirst search efficiently in a pure functional language has only become possible with the advent of imperative functional programming. In this paper we mix the techniques of pure functional programming in the s...
Depth-first search is the key to a wide variety of graph algorithms. In this paper we express depth-first search in a lazy functional language, obtaining a linear-time implementation. Unlike traditional imperative presentations, we use the structuring methods of functional languages to construct algorithms from individual reusable components. This...
In this paper we argue for the importance of lazy state, that is, sequences of imperative (destructive) actions in which the actions are delayed until their results are required. This enables state-based computations to take advantage of the control power of lazy evaluation. We provide some examples of its use, and describe an implementation within...
Giving a good research talk is not easy. We try to identify some things which we have found helpful, in the hope that they may be useful to you.
Many semantic analyses of functional languages have been developed using the Cousots’ abstract interpretation framework. Some operate on abstract values representing the past history of the computation, and are therefore called forwards analyses. Others propagate abstract contexts representing the future of the computation, and are called backwards...
Program analyses are often presented as one of two brands: forwards or backwards. In this paper we explore the significance of the direction of analysis, and show how arbitrary abstract interpretations may be reversed.
When attempting self-application of a partial evaluator written in and for a strongly-typed language several problems arise that do not seem to occur in the untyped world. These problems have hindered the production of a self-applicable partial evaluator in such languages for a number of years. In this paper we report on what is, to the best of our...
Binding-time analysis has received increased att ention in the literature recently due to its importance in partial evaluation. This mimics the growth in int crest over the last decade in strictness analysis, due to its implications for code quality of compiled lazy functional languages. In this paper we eXamine both analyses in a common framework,...
We review the theory of admissibility, the relevant aspects of retracts, and give a proof that more predicates are admissible on a subdomain of a domain than on the domain itself. We consider strictness analysis, and conclude that there are cases where conducting a proof over a subdomain is sufficient.
In partial evaluation, the separation between static and dynamic components of a data structure has traditionally been expressed in terms of products. However, this corresponds to a special case only, and there are many common examples where it is insufficiently descriptive. In this paper we show that domain projections define decompositions of dom...
Side effects in imperative programming languages are ubiquitous, which makes it difficult to reason about programs in other than operational terms. Functional programming languages, on the other hand, claim the advantage that equational logics are sufficient for reasoning, but at the price that useful effects, such as interactive input, exceptions,...
Recent work on recursion over the values of monadic ac- tions resulted in the introduction of a family of xed point operators, one for each dieren t kind of monadic eect. In the context of Haskell, the function xIO is the correspond- ing operator for the IO monad. Unfortunately, both the IO monad and x IO are language primitives in Haskell, i.e. th...