John Hughes 0001

dblp:h/JohnHughes · also R. John M. Hughes · DBLP profile ↗
← Back
38ranked-venue papers
16as first author
2since 2021 · last 2024
0000-0001-8042-0969ORCID · verified

Domains — the database's venue-derived domains; a paper can count in several

Software engineering, systems software and programming languages · 27 · 10 first-author · 2 since 2021Theory of computation · 6 · 5 first-authorSystems, architecture and hardware · 2Security and privacy · 1Databases, data management, data science and information retrieval · 1 · 1 first-authorHuman-computer interaction and ubiquitous computing · 1Applied, interdisciplinary, general and emerging computing · 1 · 1 first-author
YearPublicationVenuePosition
2024 Exploring API behaviours through generated examples
abstract
Abstract Understanding the behaviour of a system’s API can be hard. Giving users access to relevant examples of how an API behaves has been shown to make this easier for them. In addition, such examples can be used to verify expected behaviour or identify unwanted behaviours. Methods for automatically generating examples have existed for a long time. However, state-of-the-art methods rely on either white-box information, such as source code, or on formal specifications of the system behaviour. But what if you do not have access to either? This may be the case, for example, when interacting with a third-party API. In this paper, we present an approach to automatically generate relevant examples of behaviours of an API, without requiring either source code or a formal specification of behaviour. Evaluation on an industry-grade REST API shows that our method can produce small and relevant examples that can help engineers to understand the system under exploration.
John Hughes 0001, Robbert Jongeling, Adnan Causevic, Daniel Sundmark
Softw. Qual. J.2
2021 Do Judge a Test by its Cover - Combining Combinatorial and Property-Based Testing
abstract
Abstract Property-based testing uses randomly generated inputs to validate high-level program specifications. It can be shockingly effective at finding bugs, but it often requires generating a very large number of inputs to do so. In this paper, we apply ideas from combinatorial testing , a powerful and widely studied testing methodology, to modify the distributions of our random generators so as to find bugs with fewer tests. The key concept is combinatorial coverage , which measures the degree to which a given set of tests exercises every possible choice of values for every small combination of input features. In its “classical” form, combinatorial coverage only applies to programs whose inputs have a very particular shape—essentially, a Cartesian product of finite sets. We generalize combinatorial coverage to the richer world of algebraic data types by formalizing a class of sparse test descriptions based on regular tree expressions. This new definition of coverage inspires a novel combinatorial thinning algorithm for improving the coverage of random test generators, requiring many fewer tests to catch bugs. We evaluate this algorithm on two case studies, a typed evaluator for System F terms and a Haskell compiler, showing significant improvements in both.
Harrison Goldstein, John Hughes 0001, Leonidas Lampropoulos, Benjamin C. Pierce
ESOP2
2018 Special issue on Parallel and distributed computing based on the functional programming paradigm
abstract
Over a decade after the beginning of the multicore revolution, researchers and industry are still struggling with problems related to using concurrent hardware. Discovering or developing proper means for creating efficient, scalable, and adaptable software for multicore and multimode computers is still an open and a very important problem. Great efforts are made to solve problems related to the efficiency of resource utilization,1-3 monitoring and failure handling,4, 5 and, most importantly, development of highly concurrent systems.6-8 In addition to much work on adapting existing imperative technologies to the new challenges, we can observe a very interesting trend toward using the functional paradigm. The concepts of functional programming languages are very well suited to concurrent systems. Referential transparency, lazy evaluation, control over side-effects, immutable variables, and functions as first-class citizens help define maintainable and scalable solutions to the basic problems of parallel computing. The advantages of such an approach are clearly visible in HPC environments, where massively parallel solutions are needed. Providing novel services and solutions for the complex real-life problems of modern societies creates a growing demand for very fast solutions to computationally demanding problems. For example, planning complex urban road systems requires gathering results from large-scale simulations,9, 10 which are only feasible using massive parallelization. Similarly, in real-time scheduling tasks, complex optimization problems have to be solved within a single second.11, 12 Such challenges can greatly benefit from technologies based on the functional paradigm, which simplify the development process and lower the barrier for utilizing modern HPC hardware. In this special section, we have three interesting papers focusing on different issues arising in highly concurrent and distributed systems. They all adopt the functional paradigm and show its potential to solve problems of efficient utilization of available hardware. The first paper, authored by Krzywicki et al,8 tackles concurrent computations expressed using the agent paradigm. The paper introduces a new formal description of the execution model for agent-based computing systems in the form of an adaptive dataflow decoupled from the domain-specific semantics of the computation. The authors have shown that the execution models studied in previous work can be unified in this common model. The parameters of the model, such as queuing policies and granularity of the data in the flow are analyzed. Several queueing alternatives are benchmarked to demonstrate how they affect the efficiency of the computation. Using the example of a multi-agent evolutionary optimization problem solver, the new approach is shown to outperform the classic one. This proposed model is well suited to functional languages and can be easily mapped onto different classes of hardware—from simple single-core computers to distributed environments. The second paper, authored by Berenyi et al,3 focuses on linear algebraic expressions, stating that they are the essence of many computationally intensive problems, including scientific simulations and machine learning applications. However, translating high-level formulations of these expressions to efficient machine-level representations is far from trivial: developers should be assisted by automatic optimization tools so that they can focus their attention on high-level problems rather than low-level details. The tractability of these optimizations is highly dependent on the choice of the primitive constructs in terms of which the computations are expressed. In this work, the authors propose describing operations on multi-dimensional arrays using a selection of higher-order functions, inspired by functional programming, and present rewrite rules for these that can optimize them automatically for modern hierarchical and heterogeneous architectures. Using this formalism, the authors systematically construct and analyze different subdivisions and permutations of the dense matrix multiplication problem. The final paper, authored by Ciolczyk et al,5 focuses on the problem of tracing agent-based systems at large scale. At scale, assuming of course that the system considered is distributed, there are situations where processing messages within one of the actors fails—often due to failures that had occurred earlier in the system. Tracking down the origin of the failure can be difficult since existing monitoring tools only provide ways to collect metrics and statistical information about system execution. In this paper, the authors describe a new tool for tracing distributed actor systems—the Akka Tracing Tool—which allows users to generate a trace graph of messages. To address the distributed nature of the environment, the authors propose an efficient data collection mechanism based on the one-way replication technique implemented in CouchDB—a popular document database. The tool was evaluated in a distributed environment of up to 50 nodes, set up in the Amazon Web Services computing cloud, on a real application: car traffic simulation. The overhead measured when tracing all messages was between 39% to 45% on average. The library also proved to be scalable with respect to the number of nodes in the actor system and to be user-friendly. Thanks to these properties, the authors expect that the tool can simplify finding errors and speed up the development process of actor systems. The renaissance of the functional paradigm is a fact—languages like Haskell and Erlang find more and more industrial applications, and functional concepts are being introduced into classic object-oriented technologies such as Java and .NET. While this trend may not result in a complete paradigm-shift, “paradigm-mix” is already well established. The concepts inspired by functional approach help in building highly concurrent systems in various technologies. Nevertheless, many problems of massive parallelism still remain open. We believe that the work presented in this special section is a valuable step toward methods for building efficient, scalable, and robust software for modern multicore and multimode hardware platforms.
Wojciech Turek, Aleksander Byrski, John Hughes 0001, Kevin Hammond, Marek Zaionc
Concurr. Comput. Pract. Exp.3
2018 Special section on functional paradigm for high performance computing
Aleksander Byrski, Katarzyna Rycerz, John Hughes 0001, Kevin Hammond
Future Gener. Comput. Syst.3
2017 Beginner's luck: a language for property-based generators
abstract
Property-based random testing à la QuickCheck requires building efficient generators for well-distributed random data satisfying complex logical predicates, but writing these generators can be difficult and error prone. We propose a domain-specific language in which generators are conveniently expressed by decorating predicates with lightweight annotations to control both the distribution of generated values and the amount of constraint solving that happens before each variable is instantiated. This language, called Luck, makes generators easier to write, read, and maintain.
Leonidas Lampropoulos, Diane Gallois-Wong, Catalin Hritcu, John Hughes 0001, Benjamin C. Pierce, Li-yao Xia
POPL4
2016 How Well are Your Requirements Tested?
abstract
We address the question: to what extent does covering requirements ensure that a test suite is effective at revealing faults? To answer it, we generate minimal test suites that coverall requirements, and assess the tests they contain. They turn out to be very poor -- ultimately because the notion of covering a requirement is more subtle than it appears to be at first. We propose several improvements to requirements tracking during testing, which enable us to generate minimal test suites close to what a human developer would write. However, there remains a class of plausible bugs which such suites are very poor at finding, but which random testing finds rather easily.
Thomas Arts, John Hughes 0001
ICST2
2016 Mysteries of DropBox: Property-Based Testing of a Distributed Synchronization Service
abstract
File synchronization services such as Dropbox are used by hundreds ofmillions of people to replicate vital data. Yet rigorous models of theirbehavior are lacking. We present the first formal -- and testable -- model ofthe core behavior of a modern file synchronizer, and we use it to discoversurprising behavior in two widely deployed synchronizers. Our model isbased on a technique for testing nondeterministic systems that avoidsrequiring that the system's internal choices be made visible to the testing framework.
John Hughes 0001, Benjamin C. Pierce, Thomas Arts, Ulf Norell
ICST1
2016 Automatic Grading of Programming Exercises using Property-Based Testing
abstract
We present a framework for automatic grading of programming exercises using property-based testing, a form of model-based black-box testing. Models are developed to assess both the functional behaviour of programs and their algorithmic complexity. From the functional correctness model a large number of test cases are derived automatically. Executing them on the body of exercises gives rise to a (partial) ranking of programs, so that a program A is ranked higher than program B if it fails a strict subset of the test cases failed by B. The model for algorithmic complexity is used to compute worst-case complexity bounds. The framework moreover considers code structural metrics, such as McCabe's cyclomatic complexity, giving rise to a composite program grade that includes both functional, non-functional, and code structural aspects. The framework is evaluated in a course teaching algorithms and data structures using Java.
Clara Benac Earle, Lars-Åke Fredlund, John Hughes 0001
ITiCSE3
2016 Testing noninterference, quickly
abstract
Abstract Information-flow control mechanisms are difficult both to design and to prove correct. To reduce the time wasted on doomed proof attempts due to broken definitions, we advocate modern random-testing techniques for finding counterexamples during the design process. We show how to use QuickCheck, a property-based random-testing tool, to guide the design of increasingly complex information-flow abstract machines, leading up to a sophisticated register machine with a novel and highly permissive flow-sensitive dynamic enforcement mechanism that is sound in the presence of first-class public labels. We find that both sophisticated strategies for generating well-distributed random programs and readily falsifiable formulations of noninterference properties are critically important for efficient testing. We propose several approaches and evaluate their effectiveness on a collection of injected bugs of varying subtlety. We also present an effective technique for shrinking large counterexamples to minimal, easily comprehensible ones. Taken together, our best methods enable us to quickly and automatically generate simple counterexamples for more than 45 bugs. Moreover, we show how testing guides the discovery of the sophisticated invariants needed for the noninterference proof of our most complex machine.
Catalin Hritcu, Leonidas Lampropoulos, Antal Spector-Zabusky, Arthur Azevedo de Amorim, Maxime Dénès, John Hughes 0001, Benjamin C. Pierce, Dimitrios Vytiniotis
J. Funct. Program.6
2015 Making Random Judgments: Automatically Generating Well-Typed Terms from the Definition of a Type-System
Burke Fetscher, Koen Claessen, Michal H. Palka, John Hughes 0001, Robert Bruce Findler
ESOP4
2014 An Expressive Semantics of Mocking
Josef Svenningsson, Hans Svensson, Nicholas Smallbone, Thomas Arts, Ulf Norell, John Hughes 0001
FASE6
2014 Toward a mature industrial practice of software test automation
Hong Zhu 0002, Daniel Hoffman, John Hughes 0001, Dianxiang Xu
Softw. Qual. J.3
2013 Testing noninterference, quickly
abstract
Information-flow control mechanisms are difficult to design and labor intensive to prove correct. To reduce the time wasted on proof attempts doomed to fail due to broken definitions, we advocate modern random testing techniques for finding counterexamples during the design process. We show how to use QuickCheck, a property-based random-testing tool, to guide the design of a simple information-flow abstract machine. We find that both sophisticated strategies for generating well-distributed random programs and readily falsifiable formulations of noninterference properties are critically important. We propose several approaches and evaluate their effectiveness on a collection of injected bugs of varying subtlety. We also present an effective technique for shrinking large counterexamples to minimal, easily comprehensible ones. Taken together, our best methods enable us to quickly and automatically generate simple counterexamples for all these bugs.
Catalin Hritcu, John Hughes 0001, Benjamin C. Pierce, Antal Spector-Zabusky, Dimitrios Vytiniotis, Arthur Azevedo de Amorim, Leonidas Lampropoulos
ICFP2
2009 Finding race conditions in Erlang with QuickCheck and PULSE
abstract
We address the problem of testing and debugging concurrent, distributed Erlang applications. In concurrent programs, race conditions are a common class of bugs and are very hard to find in practice. Traditional unit testing is normally unable to help finding all race conditions, because their occurrence depends so much on timing. Therefore, race conditions are often found during system testing, where due to the vast amount of code under test, it is often hard to diagnose the error resulting from race conditions. We present three tools (QuickCheck, PULSE, and a visualizer) that in combination can be used to test and debug concurrent programs in unit testing with a much better possibility of detecting race conditions. We evaluate our method on an industrial concurrent case study and illustrate how we find and analyze the race conditions.
Koen Claessen, Michal H. Palka, Nicholas Smallbone, John Hughes 0001, Hans Svensson, Thomas Arts, Ulf T. Wiger
ICFP4
2008 A library for light-weight information-flow security in haskell
abstract
Protecting confidentiality of data has become increasingly important for computing systems. Information-flow techniques have been developed over the years to achieve that purpose, leading to special-purpose languages that guarantee information-flow security in programs. However, rather than producing a new language from scratch, information-flow security can also be provided as a library. This has been done previously in Haskell using the arrow framework. In this paper, we show that arrows are not necessary to design such libraries and that a less general notion, namely monads, is sufficient to achieve the same goals. We present a monadic library to provide information-flow security for Haskell programs. The library introduces mechanisms to protect confidentiality of data for pure computations, that we then easily, and modularly, extend to include dealing with side-effects. We also present combinators to dynamically enforce different declassification policies when release of information is required in a controlled manner. It is possible to enforce policies related to what, by whom, and when information is released or a combination of them. The well-known concept of monads together with the light-weight characteristic of our approach makes the library suitable to build applications where confidentiality of data is an issue.
Alejandro Russo, Koen Claessen, John Hughes 0001
Haskell3
2007 A Library for Secure Multi-threaded Information Flow in Haskell
abstract
Li and Zdancewic have recently proposed an approach to provide information-flow security via a library rather than producing a new language from the scratch. They have shown how to implement such a library in Haskell by using arrow combinators. However, their approach only works with computations that have no side-effects. In fact, they leave as an open question how their library, and the mechanisms in it, need to be modified to consider these kind of effects. Another absent feature in the library is support for multithreaded programs. Information-flow in multi-threaded programs still remains as a challenge, and no support for that has been implemented yet. It is not surprising, then, that the two main stream compilers that provide information-flow security, Jif and FlowCaml, lack support for multithreading. Following ideas taken from literature, this paper presents an extension to Li and Zdancewic's library that provides information-flow security in presence of reference manipulation and multithreaded programs. Moreover, an online-shopping case study has been implemented to evaluate the proposed techniques. The case study reveals that exploiting concurrency to leak secrets is feasible and dangerous in practice and how our extension helps avoiding that. To the best of our knowledge, this is the first implemented tool to guarantee information-flow security in concurrent programs and the first implementation of a case study that involves concurrency and information-flow policies.
Ta-Chung Tsai, Alejandro Russo, John Hughes 0001
CSF3
2007 QuickCheck Testing for Fun and Profit
John Hughes 0001
PADL1
2006 Fast and loose reasoning is morally correct
abstract
Functional programmers often reason about programs as if they were written in a total language, expecting the results to carry over to non-total (partial) languages. We justify such reasoning.Two languages are defined, one total and one partial, with identical syntax. The semantics of the partial language includes partial and infinite values, and all types are lifted, including the function spaces. A partial equivalence relation (PER) is then defined, the domain of which is the total subset of the partial language. For types not containing function spaces the PER relates equal values, and functions are related if they map related values to related values.It is proved that if two closed terms have the same semantics in the total language, then they have related semantics in the partial language. It is also shown that the PER gives rise to a bicartesian closed category which can be used to reason about values in the domain of the relation.
Nils Anders Danielsson, John Hughes 0001, Patrik Jansson, Jeremy Gibbons
POPL2
2005 Verifying haskell programs using constructive type theory
abstract
Proof assistants based on dependent type theory are closely related to functional programming languages, and so it is tempting to use them to prove the correctness of functional programs. In this paper, we show how Agda, such a proof assistant, can be used to prove theorems about Haskell programs. Haskell programs are translated into an Agda model of their semantics, by translating via GHC's Core language into a monadic form specially adapted to represent Haskell's polymorphism in Agda's predicative type system. The translation can support reasoning about either total values only, or total and partial values, by instantiating the monad appropriately. We claim that, although these Agda models are generated by a relatively complex translation process, proofs about them are simple and natural, and we offer a number of examples to support this claim.
Andreas Abel 0001, Marcin Benke, Ana Bove, John Hughes 0001, Ulf Norell
Haskell4
2004 Global variables in Haskell
abstract
Haskell today provides good support not only for a functional programming style, but also for an imperative one. Elements of imperative programming are needed in applications such as web servers, or to provide efficient implementations of well-known algorithms, such as many graph algorithms. However, one element of imperative programming, the global variable , is surprisingly hard to emulate in Haskell. We discuss several existing methods, none of which is really satisfactory, and finally propose a new approach based on implicit parameters. This approach is simple, safe, and efficient, although it does reveal weaknesses in Haskell's present type system.
John Hughes 0001
J. Funct. Program.1
2003 Polish parsers, step by step
abstract
We present the derivation of a space efficient parser combinator library: the constructed parsers do not keep unnecessary references to the input, produce online results and efficiently handle ambiguous grammars. The underlying techniques can be applied in many contexts where traditionally backtracking is used.We present two data types, one for keeping track of the progress of the search process, and one for representing the final result in a linear way. Once these data types are combined into a single type, we can perform a breadth-first search, while returning parts of the result as early as possible.
John Hughes 0001, S. Doaitse Swierstra
ICFP1
2002 Testing monadic code with QuickCheck
abstract
QuickCheck is a previously published random testing tool for Haskell programs. In this paper we show how to use it for testing monadic code, and in particular imperative code written using the ST monad. QuickCheck tests a program against a specification: we show that QuickCheck's specification language is sufficiently powerful to represent common forms of specifications: algebraic, model-based (both functional and relational), and pre-/post-conditional. Moreover, all these forms of specification can be used directly for testing. We define a new language of monadic properties, and make a link between program testing and the notion of observational equivalence.
Koen Claessen, John Hughes 0001
Haskell2
2000 The Correctness of Type Specialisation
John Hughes 0001
ESOP1
2000 QuickCheck: a lightweight tool for random testing of Haskell programs
abstract
Quick Check is a tool which aids the Haskell programmer in formulating and testing properties of programs. Properties are described as Haskell functions, and can be automatically tested on random input, but it is also possible to define custom test data generators. We present a number of case studies, in which the tool was successfully used, and also point out some pitfalls to avoid. Random testing is especially suitable for functional programs because properties can be stated at a fine grain. When a function is built from separately tested components, then random testing suffices to obtain good coverage of the definition under test.
Koen Claessen, John Hughes 0001
ICFP2
2000 Generalising monads to arrows
John Hughes 0001
Sci. Comput. Program.1
2000 Extending a partial evaluator which supports separate compilation
Rogardt Heldal, John Hughes 0001
Theor. Comput. Sci.2
1999 Recursion and Dynamic Data-structures in Bounded Space: Towards Embedded ML Programming
abstract
We present a functional language with a type system such that well typed programs run within stated space-bounds. The language is a strict, first-order variant of ML with constructs for explicit storage management. The type system is a variant of Tofte and Talpin's region inference system to which the notion of sized types, of Hughes, Pareto and Sabry, has been added.
John Hughes 0001, Lars Pareto
ICFP1
1998 Generalising Monads (Abstract)
John Hughes 0001
MPC1
1997 Partial Evaluation and Separate Compilation
abstract
Hitherto all partial evaluators have processed a complete program to produce a complete residual program. We are interested in treating programs as collections of modules which can be processed independently: 'separate partial evaluation', so to speak. In this paper we still assume that the original program is processed in its entirety, but we show how to specialise it to the static data bit-by-bit, generating a different module for each bit. When the program to be specialised is an interpreter, this corresponds to specialising it to one module of its object language at a time: each module of the object language gives rise to one module of the residual program.
Rogardt Heldal, John Hughes 0001
PEPM2
1997 Module-Sensitive Program Specialisation
abstract
We present an approach for specialising large programs, such as programs consisting of several modules, or libraries. This approach is based on the idea of using a compiler generator (cogen) for creating generating extensions. Generating extensions are specialisers specialised with respect to some input program. When run on some input data the generating extension produces a specialised version of the input program. Here we use the cogen to tailor modules for specialisation. This happens once and for all, independently of all other modules. The resulting module can then be used as a building block for generating extensions for complete programs, in much the same way as the original modules can be put together into complete programs. The result of running the final generating extension is a collection of residual modules, with a module structure derived from the original program.
Dirk Dussart, Rogardt Heldal, John Hughes 0001
PLDI3
1996 Proving the Correctness of Reactive Systems Using Sized Types
abstract
We have designed and implemented a type-based analysis for proving some basic properties of reactive systems. The analysis manipulates rich type expressions that contain information about the sizes of recursively defined data structures. Sized types are useful for detecting deadlocks, nontermination, and other errors in embedded programs. To establish the soundness of the analysis we have developed an appropriate semantic model of sized types.
John Hughes 0001, Lars Pareto, Amr Sabry
POPL1
1994 Reversing Abstract Interpretations
John Hughes 0001, John Launchbury
Sci. Comput. Program.1
1992 Reversing Abstract Interpretations
John Hughes 0001, John Launchbury
ESOP1
1992 Pretty-printing: An Exercise in Functional Programming
John Hughes 0001
MPC1
1992 Relational Reversal of Abstract Interpretation
John Hughes 0001, John Launchbury
J. Log. Comput.1
1992 Projections for Polymorphic First-Order Strictness Analysis
abstract
We apply the categorical properties of polymorphic functions to compile-time analysis, specifically projection-based strictness analysis. First we interpret parameterised types as functors in a suitable category, and show that they preserve monics and epics. Then we define “strong” and “weak” polymorphism, the latter admitting certain projections that are not polymorphic in the usual sense. We prove that, under the right conditions, a weakly polymorphic function is characterised by a single instance. It follows that the strictness analysis of one simple instance of a polymorphic function yields results that apply to all. We show how this theory may be applied. In comparison with earlier polymorphic strictness analysis methods, ours can apply polymorphic information to a particular instance very simply. The categorical approach simplifies our proofs, enabling them to be carried out at a higher level, and making them independent of the precise form of the programming language to be analysed. The major limitation of our results is that they apply only to first-order functions.
John Hughes 0001, John Launchbury
Math. Struct. Comput. Sci.1
1989 Why Functional Programming Matters
abstract
As software becomes more and more complex, it is more and more important to structure it well. Well-structured software is easy to write, easy to debug, and provides a collection of modules that can be re-used to reduce future programming costs. Conventional languages place conceptual limits on the way problems can be modularised. Functional languages push those limits back. In this paper we show that two features of functional languages in particular, higher-order functions and lazy evaluation, can contribute greatly to modularity. As examples, we manipulate lists and trees, program several numerical algorithms, and implement the alpha-beta heuristics (an Artificial Intelligence algorithm used in game-playing programs). Since modularity is the key to successful programming, functional languages are vitally important to the real world.
John Hughes 0001
Comput. J.1
1986 A Novel Representation of Lists and its Application to the Function "reverse"
John Hughes 0001
Inf. Process. Lett.1