Simon L. Peyton Jones

dblp:j/SimonLPeytonJones · also Simon Peyton Jones · DBLP profile ↗
← Back
164ranked-venue papers
56as first author
7since 2021 · last 2025
0000-0002-6085-1435ORCID · verified

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

Software engineering, systems software and programming languages · 149 · 53 first-author · 4 since 2021Theory of computation · 6 · 2 first-authorHuman-computer interaction and ubiquitous computing · 4 · 1 first-authorArtificial intelligence and machine learning · 3 · 3 since 2021Systems, architecture and hardware · 3Databases, data management, data science and information retrieval · 1 · 1 since 2021Graphics, computer vision, multimedia, augmented reality and games · 1 · 1 since 2021Applied, interdisciplinary, general and emerging computing · 1 · 1 first-author
YearPublicationVenuePosition
2025 Join Points in Practice (Keynote)
abstract
Eight years ago "Compiling without continuations" introduced the idea of so-called join points as a powerful optimisation tool in a functional language compiler. Since then join points have become more and more deeply entwined in GHC's optimisation passes; for example they are treated specially by the Simplifier and its Occurrence Analyser, and a dedicated pass called Exitification makes a join-point-specific transformation
Simon L. Peyton Jones
Haskell1
2023 The Verse Calculus: A Core Calculus for Deterministic Functional Logic Programming
abstract
Functional logic languages have a rich literature, but it is tricky to give them a satisfying semantics. In this paper we describe the Verse calculus, VC, a new core calculus for deterministic functional logic programming. Our main contribution is to equip VC with a small-step rewrite semantics, so that we can reason about a VC program in the same way as one does with lambda calculus; that is, by applying successive rewrites to it. We also show that the rewrite system is confluent for well-behaved terms.
Lennart Augustsson, Joachim Breitner, Koen Claessen, Ranjit Jhala, Simon L. Peyton Jones, Olin Shivers, Guy L. Steele Jr., Tim Sweeney
Proc. ACM Program. Lang.5
2022 CoRGi: Content-Rich Graph Neural Networks with Attention
abstract
Graph representations of a target domain often project it to a set of entities (nodes) and their relations (edges). However, such projections often miss important and rich information. For example, in graph representations used in missing value imputation, items --- represented as nodes --- may contain rich textual information. However, when processing graphs with graph neural networks (GNN), such information is either ignored or summarized into a single vector representation used to initialize the GNN. Towards addressing this, we present CoRGi, a GNN that considers the rich data within nodes in the context of their neighbors. This is achieved by endowing CoRGi's message passing with a personalized attention mechanism over the content of each node. This way, CoRGi assigns user-item-specific attention scores with respect to the words that appear in an item's content. We evaluate CoRGi on two edge-value prediction tasks and show that CoRGi is better at making edge-value predictions over existing methods, especially on sparse regions of the graph.
Angus Lamb, Simon Woodhead 0002, Simon L. Peyton Jones, Cheng Zhang 0005, Miltiadis Allamanis
KDD4
2022 Simultaneous Missing Value Imputation and Structure Learning with Groups
abstract
Learning structures between groups of variables from data with missing values is an important task in the real world, yet difficult to solve. One typical scenario is discovering the structure among topics in the education domain to identify learning pathways. Here, the observations are student performances for questions under each topic which contain missing values. However, most existing methods focus on learning structures between a few individual variables from the complete data. In this work, we propose VISL, a novel scalable structure learning approach that can simultaneously infer structures between groups of variables under missing data and perform missing value imputations with deep learning. Particularly, we propose a generative model with a structured latent space and a graph neural network-based architecture, scaling to a large number of variables. Empirically, we conduct extensive experiments on synthetic, semi-synthetic, and real-world education data sets. We show improved performances on both imputation and structure learning accuracy compared to popular and recent approaches.
Pablo Morales-Alvarez, Wenbo Gong 0001, Angus Lamb, Simon Woodhead 0002, Simon L. Peyton Jones, Nick Pawlowski, Miltiadis Allamanis, Cheng Zhang 0005
NeurIPS5
2022 Provably correct, asymptotically efficient, higher-order reverse-mode automatic differentiation
abstract
In this paper, we give a simple and efficient implementation of reverse-mode automatic differentiation, which both extends easily to higher-order functions, and has run time and memory consumption linear in the run time of the original program. In addition to a formal description of the translation, we also describe an implementation of this algorithm, and prove its correctness by means of a logical relations argument.
Faustyna Krawiec, Simon L. Peyton Jones, Neelakantan R. Krishnaswami, Tom Ellis, Richard A. Eisenberg, Andrew W. Fitzgibbon
Proc. ACM Program. Lang.2
2021 Educational Question Mining At Scale: Prediction, Analysis and Personalization
abstract
Online education platforms enable teachers to share a large number of educational resources such as questions to form exercises and quizzes for students. With large volumes of available questions, it is important to have an automated way to quantify their properties and intelligently select them for students, enabling effective and personalized learning experiences. In this work, we propose a framework for mining insights from educational questions at scale. We utilize the state-of-the-art Bayesian deep learning method, in particular partial variational auto-encoders (p-VAE), to analyze real students' answers to a large collection of questions. Based on p-VAE, we propose two novel metrics that quantify question quality and difficulty, respectively, and a personalized strategy to adaptively select questions for students. We apply our proposed framework to a real-world dataset with tens of thousands of questions and tens of millions of answers from an online education platform. Our framework not only demonstrates promising results in terms of statistical metrics but also obtains highly consistent results with domain experts' evaluation.
Zichao Wang 0001, Sebastian Tschiatschek, Simon Woodhead 0002, José Miguel Hernández-Lobato, Simon L. Peyton Jones, Richard G. Baraniuk, Cheng Zhang 0005
AAAI5
2021 Hashing modulo alpha-equivalence
abstract
In many applications one wants to identify identical subtrees of a program syntax tree. This identification should ideally be robust to alpha-renaming of the program, but no existing technique has been shown to achieve this with good efficiency (better than O(n2) in expression size). We present a new, asymptotically efficient way to hash modulo alpha-equivalence. A key insight of our method is to use a weak (commutative) hash combiner at exactly one point in the construction, which admits an algorithm with O(n (logn)2) time complexity. We prove that the use of the commutative combiner nevertheless yields a strong hash with low collision probability. Numerical benchmarks attest to the asymptotic behaviour of the method.
Krzysztof Maziarz, Tom Ellis, Alan Lawrence, Andrew W. Fitzgibbon, Simon L. Peyton Jones
PLDI5
2020 Elastic sheet-defined functions: Generalising spreadsheet functions to variable-size input arrays
abstract
Abstract Sheet-defined functions (SDFs) bring modularity and abstraction to the world of spreadsheets. Alas, end users naturally write SDFs that work over fixed-size arrays, which limits their reusability. To help end user programmers write more reusable SDFs, we describe a principled approach to generalising such functions to become elastic SDFs that work over inputs of arbitrary size. We prove that under natural, checkable conditions, our algorithm returns the principal generalisation of an input SDF. We describe a formal semantics and several efficient implementation strategies for elastic SDFs. A user study with spreadsheet users compares the human experience of programming with elastic SDFs to the alternative of relying on array-processing combinators. Our user study finds that the cognitive load of elastic SDFs is lower than for SDFs with map/reduce array combinators, the closest alternative solution.
Matt McCutchen, Judith W. Borghouts, Andrew D. Gordon 0001, Simon L. Peyton Jones, Advait Sarkar
J. Funct. Program.4
2020 Build systems à la carte: Theory and practice
abstract
Abstract Build systems are awesome, terrifying – and unloved. They are used by every developer around the world, but are rarely the object of study. In this paper, we offer a systematic, and executable, framework for developing and comparing build systems, viewing them as related points in a landscape rather than as isolated phenomena. By teasing apart existing build systems, we can recombine their components, allowing us to prototype new build systems with desired properties.
Andrey Mokhov, Neil Mitchell, Simon L. Peyton Jones
J. Funct. Program.3
2020 Kinds are calling conventions
abstract
A language supporting polymorphism is a boon to programmers: they can express complex ideas once and reuse functions in a variety of situations. However, polymorphism is pain for compilers tasked with producing efficient code that manipulates concrete values. This paper presents a new intermediate language that allows for efficient static compilation, while still supporting flexible polymorphism. Specifically, it permits polymorphism over not only the types of values, but also the representation of values, the arity of primitive machine functions, and the evaluation order of arguments---all three of which are useful in practice. The key insight is to encode information about a value's calling convention in the kind of its type, rather than in the type itself.
Paul Downen, Zena M. Ariola, Simon L. Peyton Jones, Richard A. Eisenberg
Proc. ACM Program. Lang.3
2020 Lower your guards: a compositional pattern-match coverage checker
abstract
A compiler should warn if a function defined by pattern matching does not cover its inputs—that is, if there are missing or redundant patterns. Generating such warnings accurately is difficult for modern languages due to the myriad of language features that interact with pattern matching. This is especially true in Haskell, a language with a complicated pattern language that is made even more complex by extensions offered by the Glasgow Haskell Compiler (GHC). Although GHC has spent a significant amount of effort towards improving its pattern-match coverage warnings, there are still several cases where it reports inaccurate warnings. We introduce a coverage checking algorithm called Lower Your Guards, which boils down the complexities of pattern matching into guard trees . While the source language may have many exotic forms of patterns, guard trees only have three different constructs, which vastly simplifies the coverage checking process. Our algorithm is modular, allowing for new forms of source-language patterns to be handled with little changes to the overall structure of the algorithm. We have implemented the algorithm in GHC and demonstrate places where it performs better than GHC’s current coverage checker, both in accuracy and performance.
Sebastian Graf 0004, Simon L. Peyton Jones, Ryan G. Scott
Proc. ACM Program. Lang.2
2020 A quick look at impredicativity
abstract
Type inference for parametric polymorphism is wildly successful, but has always suffered from an embarrassing flaw: polymorphic types are themselves not first class. We present Quick Look, a practical, implemented, and deployable design for impredicative type inference. To demonstrate our claims, we have modified GHC, a production-quality Haskell compiler, to support impredicativity. The changes required are modest, localised, and are fully compatible with GHC's myriad other type system extensions.
Alejandro Serrano 0001, Jurriaan Hage, Simon L. Peyton Jones, Dimitrios Vytiniotis
Proc. ACM Program. Lang.3
2019 Codata in Action
abstract
Computer scientists are well-versed in dealing with data structures. The same cannot be said about their dual: codata. Even though codata is pervasive in category theory, universal algebra, and logic, the use of codata for programming has been mainly relegated to representing infinite objects and processes. Our goal is to demonstrate the benefits of codata as a general-purpose programming abstraction independent of any specific language: eager or lazy, statically or dynamically typed, and functional or object-oriented. While codata is not featured in many programming languages today, we show how codata can be easily adopted and implemented by offering simple inter-compilation techniques between data and codata. We believe codata is a common ground between the functional and object-oriented paradigms; ultimately, we hope to utilize the Curry-Howard isomorphism to further bridge the gap.
Paul Downen, Zachary Sullivan, Zena M. Ariola, Simon L. Peyton Jones
ESOP4
2019 Higher-order type-level programming in Haskell
abstract
Type family applications in Haskell must be fully saturated. This means that all type-level functions have to be first-order, leading to code that is both messy and longwinded. In this paper we detail an extension to GHC that removes this restriction. We augment Haskell’s existing type arrow, |->|, with an unmatchable arrow, | >|, that supports partial application of type families without compromising soundness. A soundness proof is provided. We show how the techniques described can lead to substantial code-size reduction (circa 80%) in the type-level logic of commonly-used type-level libraries whilst simultaneously improving code quality and readability.
Csongor Kiss, Tony Field, Susan Eisenbach, Simon L. Peyton Jones
Proc. ACM Program. Lang.4
2019 Efficient differentiable programming in a functional array-processing language
abstract
We present a system for the automatic differentiation (AD) of a higher-order functional array-processing language. The core functional language underlying this system simultaneously supports both source-to-source forward-mode AD and global optimisations such as loop transformations. In combination, gradient computation with forward-mode AD can be as efficient as reverse mode, and that the Jacobian matrices required for numerical algorithms such as Gauss-Newton and Levenberg-Marquardt can be efficiently computed.
Amir Shaikhha, Andrew W. Fitzgibbon, Dimitrios Vytiniotis, Simon L. Peyton Jones
Proc. ACM Program. Lang.4
2018 Guarded impredicative polymorphism
abstract
The design space for type systems that support impredicative instantiation is extremely complicated. One needs to strike a balance between expressiveness, simplicity for both the end programmer and the type system implementor, and how easily the system can be integrated with other advanced type system concepts. In this paper, we propose a new point in the design space, which we call guarded impredicativity. Its key idea is that impredicative instantiation in an application is allowed for type variables that occur under a type constructor. The resulting type system has a clean declarative specification — making it easy for programmers to predict what will type and what will not —, allows for a smooth integration with GHC’s OutsideIn(X) constraint solving framework, while giving up very little in terms of expressiveness compared to systems like HMF, HML, FPH and MLF. We give a sound and complete inference algorithm, and prove a principal type property for our system.
Alejandro Serrano 0001, Jurriaan Hage, Dimitrios Vytiniotis, Simon L. Peyton Jones
PLDI4
2018 Calculation View: multiple-representation editing in spreadsheets
abstract
Spreadsheet errors are ubiquitous and costly, an unfortunate combination that is well-reported. A large class of these errors can be attributed to the inability to clearly see the underlying computational structure, as well as poor support for abstraction (encapsulation, re-use, etc). In this paper we propose a novel solution: a multiple-representation spreadsheet containing additional representations that allow abstract operations, without altering the conventional grid representation or its formula syntax. Through a user study, we demonstrate that the use of multiple representations can significantly improve user performance when performing spreadsheet authoring and debugging tasks. We close with a discussion of design implications and outline future directions for this line of inquiry.
Advait Sarkar, Andrew D. Gordon 0001, Simon L. Peyton Jones, Neil Toronto
VL/HCC3
2018 Linear Haskell: practical linearity in a higher-order polymorphic language
abstract
Linear type systems have a long and storied history, but not a clear path forward to integrate with existing languages such as OCaml or Haskell. In this paper, we study a linear type system designed with two crucial properties in mind: backwards-compatibility and code reuse across linear and non-linear users of a library. Only then can the benefits of linear types permeate conventional functional programming. Rather than bifurcate types into linear and non-linear counterparts, we instead attach linearity to function arrows . Linear functions can receive inputs from linearly-bound values, but can also operate over unrestricted, regular values. To demonstrate the efficacy of our linear type system — both how easy it can be integrated in an existing language implementation and how streamlined it makes it to write programs with linear types — we implemented our type system in ghc, the leading Haskell compiler, and demonstrate two kinds of applications of linear types: mutable data with pure interfaces; and enforcing protocols in I/O-performing functions.
Jean-Philippe Bernardy, Mathieu Boespflug, Ryan Newton, Simon L. Peyton Jones, Arnaud Spiwack
Proc. ACM Program. Lang.4
2018 Build systems à la carte
abstract
Build systems are awesome, terrifying -- and unloved. They are used by every developer around the world, but are rarely the object of study. In this paper we offer a systematic, and executable, framework for developing and comparing build systems, viewing them as related points in landscape rather than as isolated phenomena. By teasing apart existing build systems, we can recombine their components, allowing us to prototype new build systems with desired properties.
Andrey Mokhov, Neil Mitchell, Simon L. Peyton Jones
Proc. ACM Program. Lang.3
2017 Levity polymorphism
abstract
Parametric polymorphism is one of the linchpins of modern typed programming, but it comes with a real performance penalty. We describe this penalty; offer a principled way to reason about it (kinds as calling conventions); and propose levity polymorphism. This new form of polymorphism allows abstractions over calling conventions; we detail and verify restrictions that are necessary in order to compile levity-polymorphic functions. Levity polymorphism has created new opportunities in Haskell, including the ability to generalize nearly half of the type classes in GHC's standard library.
Richard A. Eisenberg, Simon L. Peyton Jones
PLDI2
2017 Compiling without continuations
abstract
Many fields of study in compilers give rise to the concept of a join point—a place where different execution paths come together. Join points are often treated as functions or continuations, but we believe it is time to study them in their own right. We show that adding join points to a direct-style functional intermediate language is a simple but powerful change that allows new optimizations to be performed, including a significant improvement to list fusion. Finally, we report on recent work on adding join points to the intermediate language of the Glasgow Haskell Compiler.
Luke Maurer, Paul Downen, Zena M. Ariola, Simon L. Peyton Jones
PLDI4
2017 Modular, higher order cardinality analysis in theory and practice
abstract
Abstract Since the mid '80s, compiler writers for functional languages (especially lazy ones) have been writing papers about identifying and exploiting thunks and lambdas that are used only once. However, it has proved difficult to achieve both power and simplicity in practice. In this paper, we describe a new, modular analysis for a higher order language, which is both simple and effective. We prove the analysis sound with respect to a standard call-by-need semantics, and present measurements of its use in a full-scale, state-of-the-art optimising compiler. The analysis finds many single-entry thunks and one-shot lambdas and enables a number of program optimisations. This paper extends our preceding conference publication (Sergey et al. 2014 Proceedings of the 41st Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages (POPL 2014) . ACM, pp. 335–348) with proofs, expanded report on evaluation and a detailed examination of the factors causing the loss of precision in the analysis.
Ilya Sergey, Dimitrios Vytiniotis, Simon L. Peyton Jones, Joachim Breitner
J. Funct. Program.3
2017 SHErrLoc: A Static Holistic Error Locator
abstract
We introduce a general way to locate programmer mistakes that are detected by static analyses. The program analysis is expressed in a general constraint language that is powerful enough to model type checking, information flow analysis, dataflow analysis, and points-to analysis. Mistakes in program analysis result in unsatisfiable constraints. Given an unsatisfiable system of constraints, both satisfiable and unsatisfiable constraints are analyzed to identify the program expressions most likely to be the cause of unsatisfiability. The likelihood of different error explanations is evaluated under the assumption that the programmer’s code is mostly correct, so the simplest explanations are chosen, following Bayesian principles. For analyses that rely on programmer-stated assumptions, the diagnosis also identifies assumptions likely to have been omitted. The new error diagnosis approach has been implemented as a tool called SHErrLoc, which is applied to three very different program analyses, such as type inference for a highly expressive type system implemented by the Glasgow Haskell Compiler—including type classes, Generalized Algebraic Data Types (GADTs), and type families. The effectiveness of the approach is evaluated using previously collected programs containing errors. The results show that when compared to existing compilers and other tools, SHErrLoc consistently identifies the location of programmer errors significantly more accurately, without any language-specific heuristics.
Danfeng Zhang, Andrew C. Myers, Dimitrios Vytiniotis, Simon L. Peyton Jones
ACM Trans. Program. Lang. Syst.4
2016 Desugaring Haskell's do-notation into applicative operations
abstract
Monads have taken the world by storm, and are supported by do-notation (at least in Haskell). Programmers are increasingly waking up to the usefulness and ubiquity of Applicatives, but they have so far been hampered by the absence of supporting notation. In this paper we show how to re-use the very same do-notation to work for Applicatives as well, providing efficiency benefits for some types that are both Monad and Applicative, and syntactic convenience for those that are merely Applicative. The result is fully implemented as an optional extension in GHC, and is in use at Facebook to make it easy to write highly-parallel queries in a distributed system.
Simon Marlow, Simon L. Peyton Jones, Edward Kmett, Andrey Mokhov
Haskell2
2016 Non-recursive make considered harmful: build systems at scale
abstract
Most build systems start small and simple, but over time grow into hairy monsters that few dare to touch. As we demonstrate in this paper, there are a few issues that cause build systems major scalability challenges, and many pervasively used build systems (e.g. Make) do not scale well.
Andrey Mokhov, Neil Mitchell, Simon L. Peyton Jones, Simon Marlow
Haskell3
2016 Pattern synonyms
abstract
Pattern matching has proven to be a convenient, expressive way of inspecting data. Yet this language feature, in its traditional form, is limited: patterns must be data constructors of concrete data types. No computation or abstraction is allowed. The data type in question must be concrete, with no ability to enforce any invariants. Any change in this data type requires all clients to update their code.
Matthew Pickering, Gergo Érdi, Simon L. Peyton Jones, Richard A. Eisenberg
Haskell3
2016 Sequent calculus as a compiler intermediate language
abstract
The λ-calculus is popular as an intermediate language for practical compilers. But in the world of logic it has a lesser-known twin, born at the same time, called the sequent calculus. Perhaps that would make for a good intermediate language, too? To explore this question we designed Sequent Core, a practically-oriented core calculus based on the sequent calculus, and used it to re-implement a substantial chunk of the Glasgow Haskell Compiler.
Paul Downen, Luke Maurer, Zena M. Ariola, Simon L. Peyton Jones
ICFP4
2016 Safe zero-cost coercions for Haskell
abstract
Abstract Generative type abstractions – present in Haskell, OCaml, and other languages – are useful concepts to help prevent programmer errors. They serve to create new types that are distinct at compile time but share a run-time representation with some base type. We present a new mechanism that allows for zero-cost conversions between generative type abstractions and their representations, even when such types are deeply nested. We prove type safety in the presence of these conversions and have implemented our work in GHC.
Joachim Breitner, Richard A. Eisenberg, Simon L. Peyton Jones, Stephanie Weirich
J. Funct. Program.3
2016 Composable scheduler activations for Haskell
abstract
Abstract The runtime for a modern, concurrent, garbage collected language like Java or Haskell is like an operating system: sophisticated, complex, performant, but alas very hard to change. If more of the runtime system were in the high-level language, it would be far more modular and malleable. In this paper, we describe a novel concurrency substrate design for the Glasgow Haskell Compiler that allows multicore schedulers for concurrent and parallel Haskell programs to be safely and modularly described as libraries in Haskell. The approach relies on abstracting the interface to the user-implemented schedulers through scheduler activations, together with the use of Software Transactional Memory to promote safety in a multicore context.
K. C. Sivaramakrishnan, Tim Harris 0001, Simon Marlow, Simon L. Peyton Jones
J. Funct. Program.4
2015 Injective type families for Haskell
abstract
Haskell, as implemented by the Glasgow Haskell Compiler (GHC), allows expressive type-level programming. The most popular type-level programming extension is TypeFamilies, which allows users to write functions on types. Yet, using type functions can cripple type inference in certain situations. In particular, lack of injectivity in type functions means that GHC can never infer an instantiation of a type variable appearing only under type functions. In this paper, we describe a small modification to GHC that allows type functions to be annotated as injective. GHC naturally must check validity of the injectivity annotations. The algorithm to do so is surprisingly subtle. We prove soundness for a simplification of our algorithm, and state and prove a completeness property, though the algorithm is not fully complete. As much of our reasoning surrounds functions defined by a simple pattern-matching structure, we believe our results extend beyond just Haskell. We have implemented our solution on a branch of GHC and plan to make it available to regular users with the next stable release of the compiler.
Jan Stolarek, Simon L. Peyton Jones, Richard A. Eisenberg
Haskell2
2015 GADTs meet their match: pattern-matching warnings that account for GADTs, guards, and laziness
abstract
For ML and Haskell, accurate warnings when a function definition has redundant or missing patterns are mission critical. But today's compilers generate bogus warnings when the programmer uses guards (even simple ones), GADTs, pattern guards, or view patterns. We give the first algorithm that handles all these cases in a single, uniform framework, together with an implementation in GHC, and evidence of its utility in practice.
Georgios Karachalias, Tom Schrijvers, Dimitrios Vytiniotis, Simon L. Peyton Jones
ICFP4
2015 Diagnosing type errors with class
abstract
Type inference engines often give terrible error messages, and the more sophisticated the type system the worse the problem. We show that even with the highly expressive type system implemented by the Glasgow Haskell Compiler (GHC)--including type classes, GADTs, and type families--it is possible to identify the most likely source of the type error, rather than the first source that the inference engine trips over. To determine which are the likely error sources, we apply a simple Bayesian model to a graph representation of the typing constraints; the satisfiability or unsatisfiability of paths within the graph provides evidence for or against possible explanations. While we build on prior work on error diagnosis for simpler type systems, inference in the richer type system of Haskell requires extending the graph with new nodes. The augmentation of the graph creates challenges both for Bayesian reasoning and for ensuring termination. Using a large corpus of Haskell programs, we show that this error localization technique is practical and significantly improves accuracy over the state of the art.
Danfeng Zhang, Andrew C. Myers, Dimitrios Vytiniotis, Simon L. Peyton Jones
PLDI4
2014 Safe zero-cost coercions for Haskell
abstract
Generative type abstractions -- present in Haskell, OCaml, and other languages -- are useful concepts to help prevent programmer errors. They serve to create new types that are distinct at compile time but share a run-time representation with some base type. We present a new mechanism that allows for zero-cost conversions between generative type abstractions and their representations, even when such types are deeply nested. We prove type safety in the presence of these conversions and have implemented our work in GHC.
Joachim Breitner, Richard A. Eisenberg, Simon L. Peyton Jones, Stephanie Weirich
ICFP3
2014 Refinement types for Haskell
abstract
SMT-based checking of refinement types for call-by-value languages is a well-studied subject. Unfortunately, the classical translation of refinement types to verification conditions is unsound under lazy evaluation. When checking an expression, such systems implicitly assume that all the free variables in the expression are bound to values. This property is trivially guaranteed by eager, but does not hold under lazy, evaluation. Thus, to be sound and precise, a refinement type system for Haskell and the corresponding verification conditions must take into account which subset of binders actually reduces to values. We present a stratified type system that labels binders as potentially diverging or not, and that (circularly) uses refinement types to verify the labeling. We have implemented our system in LIQUIDHASKELL and present an experimental evaluation of our approach on more than 10,000 lines of widely used Haskell libraries. We show that LIQUIDHASKELL is able to prove 96% of all recursive functions terminating, while requiring a modest 1.7 lines of termination-annotations per 100 lines of code.
Niki Vazou, Eric L. Seidel, Ranjit Jhala, Dimitrios Vytiniotis, Simon L. Peyton Jones
ICFP5
2014 Closed type families with overlapping equations
abstract
Open, type-level functions are a recent innovation in Haskell that move Haskell towards the expressiveness of dependent types, while retaining the look and feel of a practical programming language. This paper shows how to increase expressiveness still further, by adding closed type functions whose equations may overlap, and may have non-linear patterns over an open type universe. Although practically useful and simple to implement, these features go beyond conventional dependent type theory in some respects, and have a subtle metatheory.
Richard A. Eisenberg, Dimitrios Vytiniotis, Simon L. Peyton Jones, Stephanie Weirich
POPL3
2014 Backpack: retrofitting Haskell with interfaces
abstract
Module systems like that of Haskell permit only a weak form of modularity in which module implementations depend directly on other implementations and must be processed in dependency order. Module systems like that of ML, on the other hand, permit a stronger form of modularity in which explicit interfaces express assumptions about dependencies, and each module can be typechecked and reasoned about independently.
Scott Kilpatrick, Derek Dreyer, Simon L. Peyton Jones, Simon Marlow
POPL3
2014 Modular, higher-order cardinality analysis in theory and practice
abstract
Since the mid '80s, compiler writers for functional languages (especially lazy ones) have been writing papers about identifying and exploiting thunks and lambdas that are used only once. However it has proved difficult to achieve both power and simplicity in practice. We describe a new, modular analysis for a higher-order language, which is both simple and effective, and present measurements of its use in a full-scale, state of the art optimising compiler. The analysis finds many single-entry thunks and one-shot lambdas and enables a number of program optimisations.
Ilya Sergey, Dimitrios Vytiniotis, Simon L. Peyton Jones
POPL3
2013 Computer science as a school subject
abstract
Computer science is one of the richest, most exciting disciplines on the planet, yet any teenager will tell you that ICT (as it is called in UK schools --- "information and communication technology") is focused almost entirely on the use and application of computers, and in practice covers nothing about how computers work, nor programming, nor anything of the discipline of computer science as we understand it. Over the last two decades, computing at school has drifted from writing adventure games on the BBC Micro to writing business plans in Excel.
Simon L. Peyton Jones
ICFP1
2013 Exploiting vector instructions with generalized stream fusio
abstract
Stream fusion is a powerful technique for automatically transforming high-level sequence-processing functions into efficient implementations. It has been used to great effect in Haskell libraries for manipulating byte arrays, Unicode text, and unboxed vectors. However, some operations, like vector append, still do not perform well within the standard stream fusion framework. Others, like SIMD computation using the SSE and AVX instructions available on modern x86 chips, do not seem to fit in the framework at all.
Geoffrey Mainland, Roman Leshchinskiy, Simon L. Peyton Jones
ICFP3
2013 The computing at school working group
abstract
The Computing at School (CAS) Working Group aims to promote the teaching of computer science at school. CAS was born out of our excitement with our discipline, combined with a serious concern that many students are being "turned off" computing by a combination of factors that have conspired to make the subject seem dull and pedestrian. Our goal is to put the excitement back into Computing at school.
Simon L. Peyton Jones
ITiCSE1
2013 HALO: haskell to logic through denotational semantics
abstract
Even well-typed programs can go wrong in modern functional languages, by encountering a pattern-match failure, or simply returning the wrong answer. An increasingly-popular response is to allow programmers to write contracts that express semantic properties, such as crash-freedom or some useful post-condition. We study the static verification of such contracts. Our main contribution is a novel translation to first-order logic of both Haskell programs, and contracts written in Haskell, all justified by denotational semantics. This translation enables us to prove that functions satisfy their contracts using an off-the-shelf first-order logic theorem prover.
Dimitrios Vytiniotis, Simon L. Peyton Jones, Koen Claessen, Dan Rosén
POPL2
2013 Evidence Normalization in System FC (Invited Talk)
abstract
System FC is an explicitly typed language that serves as the target language for Haskell source programs. System FC is based on System F with the addition of erasable but explicit type equality proof witnesses. Equality proof witnesses are generated from type inference performed on source Haskell programs. Such witnesses may be very large objects, which causes performance degradation in later stages of compilation, and makes it hard to debug the results of type inference and subsequent program transformations. In this paper we present an equality proof simplification algorithm, implemented in GHC, which greatly reduces the size of the target System FC programs.
Dimitrios Vytiniotis, Simon L. Peyton Jones
RTA2
2013 Bringing computer science back into schools: lessons from the UK
abstract
Computer science in UK schools is a subject in decline: the ratio of Computing to Maths A-Level students (i.e. ages 16--18) has fallen from 1:2 in 2003 to 1:20 in 2011 and in 2012. In 2011 and again in 2012, the ratio for female students was 1:100, with less than 300 female students taking Computing A-Level in the whole of the UK each year. Similar problems have been observed in the USA and other countries, despite the increased need for computer science skills caused by IT growth in industry and society. In the UK, the Computing At School (CAS) group was formed to try to improve the state of computer science in schools. Using a combination of grassroots teacher activities and policy lobbying at a national level, CAS has been able to rapidly gain traction in the fight for computer science in schools. We examine the reasons for this success, the challenges and dangers that lie ahead, and suggest how the experience of CAS in the UK can benefit other similar organisations, such as the CSTA in the USA.
Neil Brown 0001, Michael Kölling, Tom Crick, Simon L. Peyton Jones, Simon Humphreys, Sue Sentance
SIGCSE4
2012 Lazy v. Yield: Incremental, Linear Pretty-Printing
Oleg Kiselyov, Simon L. Peyton Jones, Amr Sabry
APLAS2
2012 Vectorisation avoidance
abstract
Flattening nested parallelism is a vectorising code transform that converts irregular nested parallelism into flat data parallelism. Although the result has good asymptotic performance, flattening thoroughly restructures the code. Many intermediate data structures and traversals are introduced, which may or may not be eliminated by subsequent optimisation. We present a novel program analysis to identify parts of the program where flattening would only introduce overhead, without appropriate gain. We present empirical evidence that avoiding vectorisation in these cases leads to more efficient programs than if we had applied vectorisation and then relied on array fusion to eliminate intermediates from the resulting code.
Gabriele Keller, Manuel M. T. Chakravarty, Roman Leshchinskiy, Ben Lippmeier, Simon L. Peyton Jones
Haskell5
2012 Guiding parallel array fusion with indexed types
abstract
We present a refined approach to parallel array fusion that uses indexed types to specify the internal representation of each array. Our approach aids the client programmer in reasoning about the performance of their program in terms of the source code. It also makes the intermediate code easier to transform at compile-time, resulting in faster compilation and more reliable runtimes. We demonstrate how our new approach improves both the clarity and performance of several end-user written programs, including a fluid flow solver and an interpolator for volumetric data.
Ben Lippmeier, Manuel M. T. Chakravarty, Gabriele Keller, Simon L. Peyton Jones
Haskell4
2012 Safe haskell
abstract
Though Haskell is predominantly type-safe, implementations contain a few loopholes through which code can bypass typing and module encapsulation. This paper presents Safe Haskell, a language extension that closes these loopholes. Safe Haskell makes it possible to confine and safely execute untrusted, possibly malicious code. By strictly enforcing types, Safe Haskell allows a variety of different policies from API sandboxing to information-flow control to be implemented easily as monads. Safe Haskell is aimed to be as unobtrusive as possible. It enforces properties that programmers tend to meet already by convention. We describe the design of Safe Haskell and an implementation (currently shipping with GHC) that infers safety for code that lies in a safe subset of the language. We use Safe Haskell to implement an online Haskell interpreter that can securely execute arbitrary untrusted code with no overhead. The use of Safe Haskell greatly simplifies this task and allows the use of a large body of existing code and tools.
David Terei, Simon Marlow, Simon L. Peyton Jones, David Mazières
Haskell3
2012 Work efficient higher-order vectorisation
abstract
Existing approaches to higher-order vectorisation, also known as flattening nested data parallelism, do not preserve the asymptotic work complexity of the source program. Straightforward examples, such as sparse matrix-vector multiplication, can suffer a severe blow-up in both time and space, which limits the practicality of this method. We discuss why this problem arises, identify the mis-handling of index space transforms as the root cause, and present a solution using a refined representation of nested arrays. We have implemented this solution in Data Parallel Haskell (DPH) and present benchmarks showing that realistic programs, which used to suffer the blow-up, now have the correct asymptotic work complexity. In some cases, the asymptotic complexity of the vectorised program is even better than the original.
Ben Lippmeier, Manuel M. T. Chakravarty, Gabriele Keller, Roman Leshchinskiy, Simon L. Peyton Jones
ICFP5
2012 Equality proofs and deferred type errors: a compiler pearl
abstract
The Glasgow Haskell Compiler is an optimizing compiler that expresses and manipulates first-class equality proofs in its intermediate language. We describe a simple, elegant technique that exploits these equality proofs to support deferred type errors. The technique requires us to treat equality proofs as possibly-divergent terms; we show how to do so without losing either soundness or the zero-overhead cost model that the programmer expects.
Dimitrios Vytiniotis, Simon L. Peyton Jones, José Pedro Magalhães
ICFP2
2011 Termination combinators forever
abstract
We describe a library-based approach to constructing termination tests suitable for controlling termination of symbolic methods such as partial evaluation, supercompilation and theorem proving. With our combinators, all termination tests are correct by construction. We show how the library can be designed to embody various optimisations of the termination tests, which the user of the library takes advantage of entirely transparently.
Max Bolingbroke, Simon L. Peyton Jones, Dimitrios Vytiniotis
Haskell2
2011 Towards Haskell in the cloud
abstract
We present Cloud Haskell, a domain-specific language for developing programs for a distributed computing environment. Implemented as a shallow embedding in Haskell, it provides a message-passing communication model, inspired by Erlang, without introducing incompatibility with Haskell's established shared-memory concurrency. A key contribution is a method for serializing function closures for transmission across the network. Cloud Haskell has been implemented; we present example code and some preliminary performance measurements.
Jeff Epstein, Andrew P. Black, Simon L. Peyton Jones
Haskell3
2011 A monad for deterministic parallelism
abstract
We present a new programming model for deterministic parallel computation in a pure functional language. The model is monadic and has explicit granularity, but allows dynamic construction of dataflow networks that are scheduled at runtime, while remaining deterministic and pure. The implementation is based on monadic concurrency, which has until now only been used to simulate concurrency in functional languages, rather than to provide parallelism. We present the API with its semantics, and argue that parallel execution is deterministic. Furthermore, we present a complete work-stealing scheduler implemented as a Haskell library, and we show that it performs at least as well as the existing parallel programming models in Haskell.
Simon Marlow, Ryan Newton, Simon L. Peyton Jones
Haskell3
2011 Multicore garbage collection with local heaps
abstract
In a parallel, shared-memory, language with a garbage collected heap, it is desirable for each processor to perform minor garbage collections independently. Although obvious, it is difficult to make this idea pay off in practice, especially in languages where mutation is common. We present several techniques that substantially improve the state of the art. We describe these techniques in the context of a full-scale implementation of Haskell, and demonstrate that our local-heap collector substantially improves scaling, peak performance, and robustness.
Simon Marlow, Simon L. Peyton Jones
ISMM2
2011 Generative type abstraction and type-level computation
abstract
Modular languages support generative type abstraction, ensuring that an abstract type is distinct from its representation, except inside the implementation where the two are synonymous. We show that this well-established feature is in tension with the non-parametric features of newer type systems, such as indexed type families and GADTs. In this paper we solve the problem by using kinds to distinguish between parametric and non-parametric contexts. The result is directly applicable to Haskell, which is rapidly developing support for type-level computation, but the same issues should arise whenever generativity and non-parametric features are combined.
Stephanie Weirich, Dimitrios Vytiniotis, Simon L. Peyton Jones, Steve Zdancewic
POPL3
2011 OutsideIn(X) Modular type inference with local assumptions
abstract
Abstract Advanced type system features, such as GADTs, type classes and type families, have proven to be invaluable language extensions for ensuring data invariants and program correctness. Unfortunately, they pose a tough problem for type inference when they are used as local type assumptions. Local type assumptions often result in the lack of principal types and cast the generalisation of local let-bindings prohibitively difficult to implement and specify. User-declared axioms only make this situation worse. In this paper, we explain the problems and – perhaps controversially – argue for abandoning local let-binding generalisation. We give empirical results that local let generalisation is only sporadically used by Haskell programmers. Moving on, we present a novel constraint-based type inference approach for local type assumptions. Our system, called OutsideIn(X) , is parameterised over the particular underlying constraint domain X, in the same way as HM(X). This stratification allows us to use a common metatheory and inference algorithm. OutsideIn(X) extends the constraints of X by introducing implication constraints on top. We describe the strategy for solving these implication constraints, which, in turn, relies on a constraint solver for X. We characterise the properties of the constraint solver for X so that the resulting algorithm only accepts programs with principal types, even when the type system specification accepts programs that do not enjoy principal types. Going beyond the general framework, we give a particular constraint solver for X = type classes + GADTs + type families, a non-trivial challenge in its own right. This constraint solver has been implemented and distributed as part of GHC 7.
Dimitrios Vytiniotis, Simon L. Peyton Jones, Tom Schrijvers, Martin Sulzmann
J. Funct. Program.2
2010 Supercompilation by evaluation
abstract
This paper shows how call-by-need supercompilation can be recast to be based explicitly on an evaluator, contrasting with standard presentations which are specified as algorithms that mix evaluation rules with reductions that are unique to supercompilation. Building on standard operational-semantics technology for call-by-need languages, we show how to extend the supercompilation algorithm to deal with recursive let expressions.
Max Bolingbroke, Simon L. Peyton Jones
Haskell2
2010 Hoopl: a modular, reusable library for dataflow analysis and transformation
abstract
Dataflow analysis and transformation of control-flow graphs is pervasive in optimizing compilers, but it is typically entangled with the details of a particular compiler. We describe Hoopl, a reusable library that makes it unusually easy to define new analyses and transformations for any compiler written in Haskell. Hoopl's interface is modular and polymorphic, and it offers unusually strong static guarantees. The implementation encapsulates state-of-the-art algorithms (interleaved analysis and rewriting, dynamic error isolation), and it cleanly separates their tricky elements so that they can be understood independently.
Norman Ramsey, João Dias 0005, Simon L. Peyton Jones
Haskell3
2010 Regular, shape-polymorphic, parallel arrays in Haskell
abstract
We present a novel approach to regular, multi-dimensional arrays in Haskell. The main highlights of our approach are that it (1) is purely functional, (2) supports reuse through shape polymorphism, (3) avoids unnecessary intermediate structures rather than relying on subsequent loop fusion, and (4) supports transparent parallelisation.
Gabriele Keller, Manuel M. T. Chakravarty, Roman Leshchinskiy, Simon L. Peyton Jones, Ben Lippmeier
ICFP4
2009 Classes, Jim, But Not as We Know Them - Type Classes in Haskell: What, Why, and Whither
Simon L. Peyton Jones
ECOOP1
2009 Finding the needle: stack traces for GHC
abstract
Even Haskell programs can occasionally go wrong.Programs calling head on an empty list, and incomplete patterns in function definitions can cause program crashes, reporting little more than the precise location where error was ultimately called.Being told that one application of the head function in your program went wrong, without knowing which use of head went wrong can be infuriating.We present our work on adding the ability to get stack traces out of GHC, for example that our crashing head was used during the evaluation of foo, which was called during the evaluation of bar , during the evaluation of main.We provide a transformation that converts GHC Core programs into ones that pass a stack around, and a stack library that ensures bounded heap usage despite the highly recursive nature of Haskell.We call our extension to GHC StackTrace.
Tristan Oliver Richard Allwood, Simon L. Peyton Jones, Susan Eisenbach
Haskell2
2009 Types are calling conventions
abstract
It is common for compilers to derive the calling convention of a function from its type. Doing so is simple and modular but misses many optimisation opportunities, particularly in lazy, higher-order functional languages with extensive use of currying. We restore the lost opportunities by defining Strict Core, a new intermediate language whose type system makes the missing distinctions: laziness is explicit, and functions take multiple arguments and return multiple results.
Max Bolingbroke, Simon L. Peyton Jones
Haskell2
2009 Runtime support for multicore Haskell
abstract
Purely functional programs should run well on parallel hardware because of the absence of side effects, but it has proved hard to realise this potential in practice. Plenty of papers describe promising ideas, but vastly fewer describe real implementations with good wall-clock performance. We describe just such an implementation, and quantitatively explore some of the complex design tradeoffs that make such implementations hard to build. Our measurements are necessarily detailed and specific, but they are reproducible, and we believe that they offer some general insights.
Simon Marlow, Simon L. Peyton Jones, Satnam Singh
ICFP2
2009 Complete and decidable type inference for GADTs
abstract
GADTs have proven to be an invaluable language extension, for ensuring data invariants and program correctness among others. Unfortunately, they pose a tough problem for type inference: we lose the principal-type property, which is necessary for modular type inference.
Tom Schrijvers, Simon L. Peyton Jones, Martin Sulzmann, Dimitrios Vytiniotis
ICFP2
2009 Static contract checking for Haskell
abstract
Program errors are hard to detect and are costly both to programmers who spend significant efforts in debugging, and for systems that are guarded by runtime checks. Static verification techniques have been applied to imperative and object-oriented languages, like Java and C#, but few have been applied to a higher-order lazy functional language, like Haskell. In this paper, we describe a sound and automatic static verification framework for Haskell, that is based on contracts and symbolic execution. Our approach is modular and gives precise blame assignments at compile-time in the presence of higher-order functions and laziness.
Dana N. Xu, Simon L. Peyton Jones, Koen Claessen
POPL2
2008 Harnessing the Multicores: Nested Data Parallelism in Haskell
Simon L. Peyton Jones
APLAS1
2008 Harnessing the Multicores: Nested Data Parallelism in Haskell
abstract
If you want to program a parallel computer, a purely functional language like Haskell is a promising starting point. Since the language is pure, it is by-default safe for parallel evaluation, whereas imperative languages are by-default unsafe. But that doesn\'t make it easy! Indeed it has proved quite difficult to get robust, scalable performance increases through parallel functional programming, especially as the number of processors increases. A particularly promising and well-studied approach to employing large numbers of processors is data parallelism. Blelloch\'s pioneering work on NESL showed that it was possible to combine a rather flexible programming model (nested data parallelism) with a fast, scalable execution model (flat data parallelism). In this paper we describe Data Parallel Haskell, which embodies nested data parallelism in a modern, general-purpose language, implemented in a state-of-the-art compiler, GHC. We focus particularly on the vectorisation transformation, which transforms nested to flat data parallelism.
Simon L. Peyton Jones, Roman Leshchinskiy, Gabriele Keller, Manuel M. T. Chakravarty
FSTTCS1
2008 Type checking with open type functions
abstract
We report on an extension of Haskell with open type-level functions and equality constraints that unifies earlier work on GADTs, functional dependencies, and associated types. The contribution of the paper is that we identify and characterise the key technical challenge of entailment checking; and we give a novel, decidable, sound, and complete algorithm to solve it, together with some practically-important variants. Our system is implemented in GHC, and is already in active use.
Tom Schrijvers, Simon L. Peyton Jones, Manuel M. T. Chakravarty, Martin Sulzmann
ICFP2
2008 FPH: first-class polymorphism for Haskell
abstract
Languages supporting polymorphism typically have ad-hoc restrictions on where polymorphic types may occur. Supporting "firstclass" polymorphism, by lifting those restrictions, is obviously desirable, but it is hard to achieve this without sacrificing type inference. We present a new type system for higher-rank and impredicative polymorphism that improves on earlier proposals: it is an extension of Damas-Milner; it relies only on System F types; it has a simple, declarative specification; it is robust to program transformations; and it enjoys a complete and decidable type inference algorithm.
Dimitrios Vytiniotis, Stephanie Weirich, Simon L. Peyton Jones
ICFP3
2008 Parallel generational-copying garbage collection with a block-structured heap
abstract
We present a parallel generational-copying garbage collector implemented for the Glasgow Haskell Compiler. We use a block-structured memory allocator, which provides a natural granularity for dividing the work of GC between many threads, leading to a simple yet effective method for parallelising copying GC. The results are encouraging: we demonstrate wall-clock speedups of on average a factor of 2 in GC time on a commodity 4-core machine with no programmer intervention, compared to our best sequential GC.
Simon Marlow, Tim Harris 0001, Roshan P. James, Simon L. Peyton Jones
ISMM4
2008 Scrap Your Type Applications
Barry Jay, Simon L. Peyton Jones
MPC2
2007 Comprehensive comprehensions
abstract
We propose an extension to list comprehensions that makes it easy to express the kind of queries one would write in SQL using ORDER BY, GROUP BY, and LIMIT. Our extension adds expressive power to comprehensions, and generalises the SQL constructs that inspired it. It is easy to implement, using simple desugaring rules.
Simon L. Peyton Jones, Philip Wadler
Haskell1
2007 Lightweight concurrency primitives for GHC
abstract
The Glasgow Haskell Compiler (GHC) has quite sophisticated support for concurrency in its runtime system, which is written in low-level C code. As GHC evolves, the runtime system becomes increasingly complex, error-prone, difficult to maintain and difficult to add new concurrency features.
Simon Marlow, Simon L. Peyton Jones, Andrew P. Tolmach
Haskell3
2007 Call-pattern specialisation for haskell programs
abstract
User-defined data types, pattern-matching, and recursion are ubiquitous features of Haskell programs. Sometimes a function is called with arguments that are statically known to be in constructor form, so that the work of pattern-matching is wasted. Even worse, the argument is sometimes freshly-allocated, only to be immediately decomposed by the function.
Simon L. Peyton Jones
ICFP1
2007 Faster laziness using dynamic pointer tagging
abstract
In the light of evidence that Haskell programs compiled by GHC exhibit large numbers of mispredicted branches on modern processors, we re-examine the "tagless" aspect of the STG-machine that GHC uses as its evaluation model.
Simon Marlow, Alexey Rodriguez Yakushev, Simon L. Peyton Jones
ICFP3
2007 A monadic framework for delimited continuations
abstract
Abstract Delimited continuations are more expressive than traditional abortive continuations and they apparently require a framework beyond traditional continuation-passing style (CPS). We show that this is not the case: standard CPS is sufficient to explain the common control operators for delimited continuations. We demonstrate this fact and present an implementation as a Scheme library. We then investigate a typed account of delimited continuations that makes explicit where control effects can occur. This results in a monadic framework for typed and encapsulated delimited continuations, which we design and implement as a Haskell library.
R. Kent Dybvig, Simon L. Peyton Jones, Amr Sabry
J. Funct. Program.2
2007 Practical type inference for arbitrary-rank types
abstract
Abstract Haskell's popularity has driven the need for ever more expressive type system features, most of which threaten the decidability and practicality of Damas-Milner type inference. One such feature is the ability to write functions with higher-rank types – that is, functions that take polymorphic functions as their arguments. Complete type inference is known to be undecidable for higher-rank (impredicative) type systems, but in practice programmers are more than willing to add type annotations to guide the type inference engine, and to document their code. However, the choice of just what annotations are required, and what changes are required in the type system and its inference algorithm, has been an ongoing topic of research. We take as our starting point a λ-calculus proposed by Odersky and Läufer. Their system supports arbitrary-rank polymorphism through the exploitation of type annotations on λ-bound arguments and arbitrary sub-terms. Though elegant, and more convenient than some other proposals, Odersky and Läufer's system requires many annotations. We show how to use local type inference (invented by Pierce and Turner) to greatly reduce the annotation burden, to the point where higher-rank types become eminently usable. Higher-rank types have a very modest impact on type inference. We substantiate this claim in a very concrete way, by presenting a complete type-inference engine, written in Haskell, for a traditional Damas-Milner type system, and then showing how to extend it for higher-rank types. We write the type-inference engine using a monadic framework: it turns out to be a particularly compelling example of monads in action. The paper is long, but is strongly tutorial in style. Although we use Haskell as our example source language, and our implementation language, much of our work is directly applicable to any ML-like functional language.
Simon L. Peyton Jones, Dimitrios Vytiniotis, Stephanie Weirich, Mark Shields
J. Funct. Program.1
2007 Understanding functional dependencies via constraint handling rules
abstract
Abstract Functional dependencies are a popular and useful extension to Haskell style type classes. We give a reformulation of functional dependencies in terms of Constraint Handling Rules (CHRs). In previous work, CHRs have been employed for describing user-programmable type extensions in the context of Haskell style type classes. Here, we make use of CHRs to provide for the first time a concise result that under some sufficient conditions, functional dependencies allow for sound, complete and decidable type inference. The sufficient conditions imposed on functional dependencies can be very limiting. We show how to safely relax these conditions and suggest several sound extensions of functional dependencies. Our results allow for a better understanding of functional dependencies and open up the opportunity for new applications.
Martin Sulzmann, Gregory J. Duck, Simon L. Peyton Jones, Peter J. Stuckey
J. Funct. Program.3
2006 Haskell Is Not Not ML
Ben Rudiak-Gould, Alan Mycroft, Simon L. Peyton Jones
ESOP3
2006 Roadmap for enhanced languages and methods to aid verification
abstract
This roadmap describes ways that researchers in four areas---specification languages, program generation, correctness by construction, and programming languages---might help further the goal of verified software. It also describes what advances the "verified software" grand challenge might anticipate or demand from work in these areas. That is, the roadmap is intended to help foster collaboration between the grand challenge and these research areas.A common goal for research in these areas is to establish language designs and tool architectures that would allow multiple annotations and tools to be used on a single program. In the long term, researchers could try to unify these annotations and integrate such tools.
Gary T. Leavens, Jean-Raymond Abrial, Don S. Batory, Michael J. Butler, Alessandro Coglio, Kathi Fisler, Eric C. R. Hehner, Cliff B. Jones, Dale Miller 0001, Simon L. Peyton Jones, Murali Sitaraman, Douglas R. Smith, Aaron Stump
GPCE10
2006 Simple unification-based type inference for GADTs
abstract
Generalized algebraic data types (GADTs), sometimes known as “guarded recursive data types ” or “first-class phantom types”, are a simple but powerful generalization of the data types of Haskell and ML. Recent works have given compelling examples of the utility of GADTs, although type inference is known to be difficult. Our contribution is to show how to exploit programmer-supplied type annotations to make the type inference task almost embarrassingly easy. Our main technical innovation is wobbly types, which express in a declarative way the uncertainty caused by the incremental nature of typical type-inference algorithms. 1.
Simon L. Peyton Jones, Dimitrios Vytiniotis, Stephanie Weirich, Geoffrey Washburn
ICFP1
2006 Boxy types: inference for higher-rank types and impredicativity
abstract
Languages with rich type systems are beginning to employ a blend of type inference and type checking, so that the type inference engine is guided by programmer-supplied type annotations. In this paper we show, for the first time, how to combine the virtues of two well-established ideas: unification-based inference, and bidi-rectional propagation of type annotations. The result is a type system that conservatively extends Hindley-Milner, and yet supports both higher-rank types and impredicativity.
Dimitrios Vytiniotis, Stephanie Weirich, Simon L. Peyton Jones
ICFP3
2006 Making a fast curry: push/enter vs. eval/apply for higher-order languages
abstract
Higher-order languages that encourage currying are typically implemented using one of two basic evaluation models: push/enter or eval/apply. Implementors use their intuition and qualitative judgements to choose one model or the other. Our goal in this paper is to provide, for the first time, a more substantial basis for this choice, based on our qualitative and quantitative experience of implementing both models in a state-of-the-art compiler for Haskell. Our conclusion is simple, and contradicts our initial intuition: compiled implementations should use eval/apply.
Simon Marlow, Simon L. Peyton Jones
J. Funct. Program.2
2005 Haskell on a shared-memory multiprocessor
abstract
Multi-core processors are coming, and we need ways to program them. The combination of purely-functional programming and explicit, monadic threads, communicating using transactional memory, looks like a particularly promising way to do so. This paper describes a full-scale implementation of shared-memory parallel Haskell, based on the Glasgow Haskell Compiler. Our main technical contribution is a lock-free mechanism for evaluating shared thunks that eliminates the major performance bottleneck in parallel evaluation of a lazy language. Our results are preliminary but promising: we can demonstrate wall-clock speedups of a serious application (GHC itself), even with only two processors, compared to the same application compiled for a uni-processor.
Tim Harris 0001, Simon Marlow, Simon L. Peyton Jones
Haskell3
2005 Associated type synonyms
abstract
Haskell programmers often use a multi-parameter type class in which one or more type parameters are functionally dependent on the first. Although such functional dependencies have proved quite popular in practice, they express the programmer's intent somewhat indirectly. Developing earlier work on associated data types, we propose to add functionally dependent types as type synonyms to type-class bodies. These associated type synonyms constitute an interesting new alternative to explicit functional dependencies.
Manuel M. T. Chakravarty, Gabriele Keller, Simon L. Peyton Jones
ICFP3
2005 Scrap your boilerplate with class: extensible generic functions
abstract
The 'Scrap your boilerplate' approach to generic programming allows the programmer to write generic functions that can traverse arbitrary data structures, and yet have type-specific cases. However, the original approach required all the type-specific cases to be supplied at once, when the recursive knot of generic function definition is tied. Hence, generic functions were closed. In contrast, Haskell's type classes support open, or extensible, functions that can be extended with new type-specific cases as new data types are defined. In this paper, we extend the 'Scrap your boilerplate' approach to support this open style. On the way, we demonstrate the desirability of abstraction over type classes, and the usefulness of recursive dictionarie.
Ralf Lämmel, Simon L. Peyton Jones
ICFP2
2005 Associated types with class
abstract
Haskell's type classes allow ad-hoc overloading, or type-indexing, of functions. A natural generalisation is to allow type-indexing of data types as well. It turns out that this idea directly supports a powerful form of abstraction called associated types, which are available in C++ using traits classes. Associated types are useful in many applications, especially for self-optimising libraries that adapt their data representations and algorithms in a type-directed manner.In this paper, we introduce and motivate associated types as a rather natural generalisation of Haskell's existing type classes. Formally, we present a type system that includes a type-directed translation into an explicitly typed target language akin to System F; the existence of this translation ensures that the addition of associated data types to an existing Haskell compiler only requires changes to the front end.
Manuel M. T. Chakravarty, Gabriele Keller, Simon L. Peyton Jones, Simon Marlow
POPL3
2005 Composable memory transactions
abstract
Writing concurrent programs is notoriously difficult, and is of increasing practical importance. A particular source of concern is that even correctly-implemented concurrency abstractions cannot be composed together to form larger abstractions. In this paper we present a new concurrency model, based on transactional memory, that offers far richer composition. All the usual benefits of transactional memory are present (e.g. freedom from deadlock), but in addition we describe new modular forms of blocking and choice that have been inaccessible in earlier work.
Tim Harris 0001, Simon Marlow, Simon L. Peyton Jones, Maurice Herlihy
PPoPP3
2004 Sound and Decidable Type Inference for Functional Dependencies
Gregory J. Duck, Simon L. Peyton Jones, Peter J. Stuckey, Martin Sulzmann
ESOP2
2004 Extending the Haskell foreign function interface with concurrency
abstract
A Haskell system that includes both the Foreign Function Interface and the Concurrent Haskell extension must consider how Concurrent Haskell threads map to external Operating System threads for the purposes of specifying in which thread a foreign call is made.Many concurrent languages take the easy route and specify a one-to-one correspondence between the language's own threads and external OS threads. However, OS threads tend to be expensive, so this choice can limit the performance and scalability of the concurrent language.The main contribution of this paper is a language design that provides a neat solution to this problem, allowing the implementor of the language enough flexibility to provide cheap lightweight threads, while still providing the programmer with control over the mapping between internal threads and external threads where necessary.
Simon Marlow, Simon L. Peyton Jones, Wolfgang Thaller
Haskell2
2004 Scrap more boilerplate: reflection, zips, and generalised casts
abstract
Writing boilerplate code is a royal pain. Generic programming promises to alleviate this pain by allowing the programmer to write a generic "recipe" for boilerplate code, and use that recipe in many places. In earlier work we introduced the "Scrap your boilerplate" approach to generic programming, which exploits Haskell's existing type-class mechanism to support generic transformations and queries.This paper completes the picture. We add a few extra "introspective" or "reflective" facilities, that together support a rich variety of serialisation and de-serialisation. We also show how to perform generic "zips", which at first appear to be somewhat tricky in our framework. Lastly, we generalise the ability to over-ride a generic function with a type-specific one.All of this can be supported in Haskell with independently-useful extensions: higher-rank types and type-safe cast. The GHC implementation of Haskell readily derives the required type classes for user-defined data types.
Ralf Lämmel, Simon L. Peyton Jones
ICFP2
2004 Making a fast curry: push/enter vs. eval/apply for higher-order languages
abstract
Higher-order languages that encourage currying are implemented using one of two basic evaluation models: push/enter or eval/apply. Implementors use their intuition and qualitative judgements to choose one model or the other.Our goal in this paper is to provide, for the first time, a more substantial basis for this choice, based on our qualitative and quantitative experience of implementing both models in a state-of-the-art compiler for Haskell.Our conclusion is simple, and contradicts our initial intuition: compiled implementations should use eval/apply.
Simon Marlow, Simon L. Peyton Jones
ICFP2
2004 The C - compiler infrastructure
abstract
No abstract available.
Norman Ramsey, Simon L. Peyton Jones
ICFP2
2004 Exploring the barrier to entry: incremental generational garbage collection for Haskell
abstract
We document the desi n and implementation of a "production" incremental garbage collector for GHC 6.2.It builds on our earlier work (Non-stop Haskell)that exploited GHC's dynamic dispatch mechanism to hijack object code pointers so that objects in to-space automatically scavenge themselves when the mutator attempts to "enter" them. This paper details various optimisations based on code specialisation that remove the dynamic space,and associated time, overheads that accompanied our earlier scheme.We detail important implementation issues and provide a detailed evaluation of a range of design alternatives in comparison with Non-stop Haskell and GHC's current generational collector.We also show how the same code specialisation techniques can be used to eliminate the write barrier in a enerational collector.
Andrew M. Cheadle, Tony Field, Simon Marlow, Simon L. Peyton Jones, Lyndon While
ISMM4
2004 Champagne Prototyping: A Research Technique for Early Evaluation of Complex End-User Programming Systems
abstract
Although a variety of evaluation techniques are available to researchers of visual and end-user programming systems, they are primarily suited to evaluation of research systems. It is important to have evaluation techniques suitable for real-world programming environments, in order to satisfy real-world product managers of the usefulness of proposed new features. To help fill this gap, we present a new evaluation technique, based in part on Cognitive Dimensions and Attention Investment, called "Champagne Prototyping". The technique is an early-evaluation technique that is inexpensive to do, yet features the credibility that comes from being based on the real commercial environment of interest, and from working with real users of the environment.
Alan F. Blackwell, Margaret M. Burnett, Simon L. Peyton Jones
VL/HCC3
2004 Constructed product result analysis for Haskell
abstract
Compilers for ML and Haskell typically go to a good deal of trouble to arrange that multiple arguments can be passed efficiently to a procedure. For some reason, less effort seems to be invested in ensuring that multiple results can also be returned efficiently. In the context of the lazy functional language Haskell, we describe an analysis, Constructed Product Result (CPR) analysis, that determines when a function can profitably return multiple results in registers. The analysis is based only on a function's definition, and not on its uses (so separate compilation is easily supported) and the results of the analysis can be expressed by a transformation of the function definition alone. We discuss a variety of design issues that were addressed in our implementation, and give measurements of the effectiveness of our approach across a substantial benchmark set. Overall, the price/performance ratio is good: the benefits are modest in general (though occasionally dramatic), but the costs in both complexity and compile time, are low.
Clement A. Baker-Finch, Kevin Glynn, Simon L. Peyton Jones
J. Funct. Program.3
2003 Scrap Your Boilerplate
Simon L. Peyton Jones, Ralf Lämmel
APLAS1
2003 HsDebug: debugging lazy programs by not being lazy
abstract
Article Share on HsDebug: debugging lazy programs by not being lazy Authors: Robert Ennals University of Cambridge University of CambridgeView Profile , Simon Peyton Jones Microsoft Research Ltd, Cambridge Microsoft Research Ltd, CambridgeView Profile Authors Info & Claims Haskell '03: Proceedings of the 2003 ACM SIGPLAN workshop on HaskellAugust 2003Pages 84–87https://doi.org/10.1145/871895.871904Published:28 August 2003Publication History 7citation345DownloadsMetricsTotal Citations7Total Downloads345Last 12 Months7Last 6 weeks0 Get Citation AlertsNew Citation Alert added!This alert has been successfully added and will be sent to:You will be notified whenever a record that you have chosen has been cited.To manage your alert preferences, click on the button below.Manage my AlertsNew Citation Alert!Please log in to your account Save to BinderSave to BinderCreate a New BinderNameCancelCreateExport CitationPublisher SiteGet Access
Robert Ennals, Simon L. Peyton Jones
Haskell2
2003 Optimistic evaluation: an adaptive evaluation strategy for non-strict programs
abstract
Lazy programs are beautiful, but they are slow because they build many thunks. Simple measurements show that most of these thunks are unnecessary: they are in fact always evaluated, or are always cheap. In this paper we describe Optimistic Evaluation --- an evaluation strategy that exploits this observation. Optimistic Evaluation complements compile-time analyses with run-time experiments: it evaluates a thunk speculatively, but has an abortion mechanism to back out if it makes a bad choice. A run-time adaption mechanism records expressions found to be unsuitable for speculative evaluation, and arranges for them to be evaluated more lazily in the future.We have implemented optimistic evaluation in the Glasgow Haskell Compiler. The results are encouraging: many programs speed up significantly (5-25%), some improve dramatically, and none go more than 15% slower.
Robert Ennals, Simon L. Peyton Jones
ICFP2
2003 A user-centred approach to functions in Excel
abstract
We describe extensions to the Excel spreadsheet that integrate userdefined functions into the spreadsheet grid, rather than treating them as a "bolt-on". Our first objective was to bring the benefits of additional programming language features to a system that is often not recognised as a programming language. Second, in a project involving the evolution of a well-established language, compatibility with previous versions is a major issue, and maintaining this compatibility was our second objective. Third and most important, the commercial success of spreadsheets is largely due to the fact that many people find them more usable than programming languages for programming-like tasks. Thus, our third objective (with resulting constraints) was to maintain this usability advantage.
Simon L. Peyton Jones, Alan F. Blackwell, Margaret M. Burnett
ICFP1
2003 Haskell 98: Introduction
abstract
Contents i Preface vii 1.1 Program Structure 3 1.2 The Haskell Kernel 4 1.3 Values and Types 4 1.4 Namespaces 5
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98: Lexical Structure
abstract
2.1 Notational Conventions 7 2.2 Lexical Program Structure 8 2.3 Comments 9 2.4 Identifiers and Operators 10 2.5 Numerical Literals 11 2.6 Character and String Literals 12 2.7 Layout 13
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98: Expressions
abstract
3.1 Errors 19 3.2 Variables, Constructors, Operators, and Literals 20 3.3 Curried Applications and Lambda Abstractions 21 3.4 Operator Applications 21 3.5 Sections 22 3.6 Conditionals 23 3.7 Lists 23 3.8 Tuples 24 3.9 Unit Expressions and Parenthesized Expessions 25 3.10 Arithmetic Sequences 25 3.11 List Comprehensions 25 3.12 Let Expressions 27 3.13 Case Expressions 27 3.14 Do Expressions 29 3.15 Datatypes with Field Labels 29 3.16 Expression Type Signatures 32 3.17 Pattern Matching 32
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98: Declarations and Bindings
abstract
4.1 Overview of Types and Classes 40 4.2 User-Defined datatypes 45 4.3 Type Classes and Overloading 49 4.4 Nested Declarations 55 4.5 Static Semantics of Function and Pattern Bindings 60 4.6 Kind Inference 66
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98: Modules
abstract
5.1 Module Structure 68 5.2 Export Lists 69 5.3 Import Declarations 71 5.4 Importing and Exporting Instance Declarations 74 5.5 Name Clashes and Closure 74 5.6 Standard Prelude 77 5.7 Separate Compilation 78 5.8 Abstract Datatypes 78
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98: Predefined Types and Classes
abstract
6.1 Standard Haskell Types 81 6.2 Strict Evaluation 84 6.3 Standard Haskell Classes 84 6.4 Numbers 91
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98: Basic Input/Output
abstract
7.1 Standard I/O Functions 97 7.2 Sequencing I/O Operations 99 7.3 Exception Handling in the I/O Monad 100
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98: Standard Prelude
abstract
8.1 Module Prelude 104 8.2 Module PreludeList 114 8.3 Module PreludeText 119 8.4 Module PreludeIO 123
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98: Syntax Reference
abstract
9.1 Notational Conventions 125 9.2 Lexical Syntax 126 9.3 Layout 128 9.4 Literate Comments 131 9.5 Context-Free Syntax 133
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98: Specification of Derived Instances
abstract
10.1 Derived Instances of Eq and Ord 140 10.2 Derived Instances of Enum 140 10.3 Derived Instances of Bounded 141 10.4 Derived Instances of Read and Show 142 10.5 An Example 143
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98: Compiler Pragmas
abstract
11.1 Inlining 145 11.2 Specialization 145
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98 Libraries: Rational Numbers
abstract
12.1 Library Ratio 150
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98 Libraries: Complex Numbers
abstract
13.1 Library Complex 154
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98 Libraries: Numeric Functions
abstract
14.1 Showing Functions 158 14.2 Reading Functions 159 14.3 Miscellaneous 159 14.4 Library Numeric 160
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98 Libraries: Indexing Operations
abstract
15.1 Deriving Instances of Ix 170 15.2 Library Ix 171
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98 Libraries: Arrays
abstract
16.1 Array Construction 174 16.2 Incremental Array Updates 175 16.3 Derived Arrays 176 16.4 Library Array 176
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98 Libraries: List Utilities
abstract
17.1 Indexing Lists 181 17.2 “Set” Operations 181 17.3 List Transformations 182 17.4 unfoldr 182 17.5 Predicates 183 17.6 The “By” Operations 183 17.7 The “generic” Operations 184 17.8 Further “zip” Operations 184 17.9 Library List 184
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98 Libraries: Maybe Utilities
abstract
18.1 Library Maybe 192
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98 Libraries: Character Utilities
abstract
19.1 Library Char 195
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98 Libraries: Monad Utilities
abstract
20.1 Naming Conventions 200 20.2 Class MonadPlus 200 20.3 Functions 201 20.4 Library Monad 202
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98 Libraries: Input/Output
abstract
21.1 I/O Errors 207 21.2 Files and Handles 208 21.3 Opening and Closing Files 210 21.4 Determining the Size of a File 211 21.5 Detecting the End of Input 211 21.6 Buffering Operations 211 21.7 Repositioning Handles 213 21.8 Handle Properties 213 21.9 Text Input and Output 214 21.10 Examples 215 21.11 Library IO 216
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98 Libraries: Directory Functions
abstract
Directory Functions 219
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98 Libraries: System Functions
abstract
System Functions 223
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98 Libraries: Dates and Times
abstract
24.1 Library Time 227
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98 Libraries: Locales
abstract
25.1 Library Locale 231
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98 Libraries: CPU Time
abstract
CPU Time 233
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98 Libraries: Random Numbers
abstract
27.1 The RandomGen class, and the StdGen generator 236 27.2 The Random class 239 27.3 The global random number generator 240
Simon L. Peyton Jones
J. Funct. Program.1
2003 Haskell 98 Libraries: Bibliography
abstract
Bibliography 241 Index 243
Simon L. Peyton Jones
J. Funct. Program.1
2003 The Educational Pearls column
Simon L. Peyton Jones, Philip Wadler
J. Funct. Program.1
2002 Template meta-programming for Haskell
abstract
We propose a new extension to the purely functional programming language Haskell that supports compile-time meta-programming. The purpose of the system is to support the algorithmic construction of programs at compile-time. The ability to generate code at compile time allows the programmer to implement such features as polytypic programs, macro-like expansion, user directed optimization (such as inlining), and the generation of supporting data structures and functions from existing data structures and functions. Our design is being implemented in the Glasgow Haskell Compiler, ghc. 1
Tim Sheard, Simon L. Peyton Jones
Haskell2
2002 Secrets of the Glasgow Haskell Compiler inliner
abstract
Higher-order languages such as Haskell encourage the programmer to build abstractions by composing functions. A good compiler must inline many of these calls to recover an efficiently executable program. In principle, inlining is dead simple: just replace the call of a function by an instance of its body. But any compiler-writer will tell you that inlining is a black art, full of delicate compromises that work together to give good performance without unnecessary code bloat. The purpose of this paper is, therefore, to articulate the key lessons we learned from a full-scale “production” inliner, the one used in the Glasgow Haskell compiler. We focus mainly on the algorithmic aspects, but we also provide some indicative measurements to substantiate the importance of various aspects of the inliner.
Simon L. Peyton Jones, Simon Marlow
J. Funct. Program.1
2001 Asynchronous Exceptions in Haskell
abstract
Asynchronous exceptions, such as timeouts are important for robust, modular programs, but are extremely difficult to program with — so much so that most programming languages either heavily restrict them or ban them altogether. We extend our earlier work, in which we added synchronous exceptions to Haskell, to support asynchronous exceptions too. Our design introduces scoped combinators for blocking and unblocking asynchronous interrupts, along with a somewhat surprising semantics for operations that can suspend. Uniquely, we also give a formal semantics for our system.
Simon Marlow, Simon L. Peyton Jones, Andrew Moran, John H. Reppy
PLDI2
2000 The Multi-architecture Performance of the Parallel Functional Language GP H (Research Note)
Philip W. Trinder, Hans-Wolfgang Loidl, Ed. Barry Jr., Kei Davis, Kevin Hammond, Ulrike Klusik, Simon L. Peyton Jones, Álvaro J. Rebón Portillo
Euro-Par7
2000 Non-stop Haskell
abstract
We describe an efficient technique for incorporating Baker's incremental garbage collection algorithm into the Spineless Tagless G-machine on stock hardware. This algorithm eliminates the stop/go execution associated with bulk copying collection algorithms, allowing the system to place an upper bound on the pauses due to garbage collection. The technique exploits the fact that objects are always accessed by jumping to code rather than being explicitly dereferenced. It works by modifying the entry code-pointer when an object is in the transient state of being evacuated but not scavenged. An attempt to enter it from the mutator causes the object to "self-scavenge" transparently before resetting its entry code pointer. We describe an implementation of the scheme in v4.01 of the Glasgow Haskell Compiler and report performance results obtained by executing a range of applications. These experiments show that the read barrier can be implemented in dynamic dispatching systems such as the STG-machine with very short mutator pause times and with negligible overhead on execution time.
Andrew M. Cheadle, Tony Field, Simon Marlow, Simon L. Peyton Jones, Lyndon While
ICFP4
2000 Composing contracts: an adventure in financial engineering, functional pearl
abstract
Financial and insurance contracts do not sound like promising territory for functional programming and formal semantics, but in fact we have discovered that insights from programming languages bear directly on the complex subject of describing and valuing a large class of contracts.We introduce a combinator library that allows us to describe such contracts precisely, and a compositional denotational semantics that says what such contracts are worth. We sketch an implementation of our combinator library in Haskell. Interestingly, lazy evaluation plays a crucial role.
Simon L. Peyton Jones, Jean-Marc Eber, Julian Seward
ICFP1
2000 A single intermediate language that supports multiple implementations of exceptions
abstract
We present mechanisms that enable our compiler-target language, C--, to express four of the best known techniques for implementing exceptions, all within a single, uniform framework. We define the mechanisms precisely, using a formal operational semantics. We also show that exceptions need not require special treatment in the optimizer; by introducing extra dataflow edges, we make standard optimization techniques work even on programs that use exceptions. Our approach clarifies the design space of exception-handling techniques, and it allows a single optimizer to handle a variety of implementation techniques. Our ultimate goal is to allow a source-language compiler the freedom to choose its exception-handling policy, while encapsulating the architecture-dependent mechanisms and their optimization in an implementation of C--that can be used by compilers for many source languages.
Norman Ramsey, Simon L. Peyton Jones
PLDI2
1999 Calling Hell From Heaven and Heaven From Hell
abstract
The increasing popularity of component-based programming tools offer a big opportunity to designers of advanced programming languages, such as Haskell. If we can package our programs as COM objects, then it is easy to integrate them into applications written in other languages. In earlier work we described a preliminary integration of Haskell with Microsoft's Component Object Model (COM), focusing on how Haskell can create and invoke COM objects. This paper develops that work, concentrating on the mechanisms that support externally-callable Haskell functions, and the encapsulation of a Haskell program as a COM object. 1 Introduction "Component-based programming" is all the rage. It has come to mean an approach to software construction in which a program is an assembly software components, perhaps written in different languages, glued together by some common substrate [16]. The most widely used substrates are Microsoft's Component Object Model (COM), and the Common Object Request Broke...
Sigbjørn Finne, Daan Leijen, Erik Meijer 0001, Simon L. Peyton Jones
ICFP4
1999 A Semantics for Imprecise Exceptions
abstract
Some modern superscalar microprocessors provide only imprecise exceptions. That is, they do not guarantee to report the same exception that would be encountered by a straightforward sequential execution of the program. In exchange, they offer increased performance or decreased chip area (which amount to much the same thing).This performance/precision tradeoff has not so far been much explored at the programming language level. In this paper we propose a design for imprecise exceptions in the lazy functional programming language Haskell. We discuss several designs, and conclude that imprecision is essential if the language is still to enjoy its current rich algebra of transformations. We sketch a precise semantics for the language extended with exceptions.The paper shows how to extend Haskell with exceptions without crippling the language or its compilers. We do not yet have enough experience of using the new mechanism to know whether it strikes an appropriate balance between expressiveness and performance.
Simon L. Peyton Jones, Alastair Reid 0001, Fergus Henderson, Tony Hoare, Simon Marlow
PLDI1
1999 Once Upon a Polymorphic Type
abstract
We present a sound type-based `usage analysis' for a realistic lazy functional language. Accurate information on the usage of program subexpressions in a lazy functional language permits a compiler to perform a number of useful optimisations. However, existing analyses are either ad-hoc and approximate, or defined over restricted languages. Our work extends the Once Upon A Type system of Turner, Mossin, and Wadler (FPCA'95). Firstly, we add type polymorphism, an essential feature of typed functional programming languages. Secondly, we include general Haskell-style user-defined algebraic data types. Thirdly, we explain and solve the `poisoning problem', which causes the earlier analysis to yield poor results. Interesting design choices turn up in each of these areas. Our analysis is sound with respect to a Launchbury-style operational semantics, and it is straightforward to implement. Good results have been obtained from a prototype implementation, and we are currently integrating the system into the Glasgow Haskell Compiler.
Keith Wansbrough, Simon L. Peyton Jones
POPL2
1999 C--: A Portable Assembly Language that Supports Garbage Collection
Simon L. Peyton Jones, Norman Ramsey, Fermin Reig
PPDP1
1999 Engineering parallel symbolic programs in GPH
abstract
We investigate the claim that functional languages offer low-cost parallelism in the context of symbolic programs on modest parallel architectures. In our investigation we present the first comparative study of the construction of large applications in a parallel functional language, in our case in Glasgow Parallel Haskell (GPH). The applications cover a range of application areas, use several parallel programming paradigms, and are measured on two very different parallel architectures. On the applications level the most significant result is that we are able to achieve modest wall-clock speedups (between factors of 2 and 10) over the optimised sequential versions for all but one of the programs. Speedups are obtained even for programs that were not written with the intention of being parallelised. These gains are achieved with a relatively small programmer-effort. One reason for the relative ease of parallelisation is the use of evaluation strategies, a new parallel programming technique that separates the algorithm from the co-ordination of parallel behaviour. On the language level we show that the combination of lazy and parallel evaluation is useful for achieving a high level of abstraction. In particular we can describe top-level parallelism, and also preserve module abstraction by describing parallelism over the data structures provided at the module interface (‘data-oriented parallelism’). Furthermore, we find that the determinism of the language is helpful, as is the largely implicit nature of parallelism in GPH. Copyright © 1999 John Wiley & Sons, Ltd.
Hans-Wolfgang Loidl, Philip W. Trinder, Kevin Hammond, Sahalu B. Junaidu, Richard G. Morgan, Simon L. Peyton Jones
Concurr. Pract. Exp.6
1998 H/Direct: A Binary Foreign Language Interface for Haskell
abstract
H/Direct is a foreign-language interface for the purely functional language Haskell. Rather than rely on host-language type signatures, H/Direct compiles Interface Definition Language (IDL) to Haskell stub code that marshals data across the interface. This approach allows Haskell to call both C and COM, and allows a Haskell component to be wrapped in a C or COM interface. IDL is a complex language and language mappings for IDL are usually described informally. In contrast, we provide a relatively formal and precise definition of the mapping between Haskell and IDL.
Sigbjørn Finne, Daan Leijen, Erik Meijer 0001, Simon L. Peyton Jones
ICFP4
1998 Scripting COM components in Haskell
abstract
The expressiveness of higher-order typed languages such as Haskell or ML makes them an attractive medium in which to write software components. Hitherto, however, their use has been limited by the all-or-nothing problem: it is hard to write just part of an application in these languages. Component-based programming using a binary standard such as Microsoft's Component Object Model (COM) offers a solution to this dilemma, by specifying a language-independent interface between components. This paper reports about our experience with exploiting this opportunity in the purely functional language Haskell. We describe a design for integrating COM components into Haskell programs, and we demonstrate why someone might want to script their COM components in this way.
Simon L. Peyton Jones, Erik Meijer 0001, Daan Leijen
ICSR1
1998 Bridging the Gulf: A Common Intermediate Language for ML and Haskell
abstract
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 language in the direction of the other. Achieving this goal without compromising the ability to Compile as good code as a more direct route turned out to be much more subtle than we expected. We address this challenge using monads and unpointed types, identify two alternative language designs, and explore the choices they embody.
Simon L. Peyton Jones, Mark Shields, John Launchbury, Andrew P. Tolmach
POPL1
1998 Dynamic Typing as Staged Type Inference
abstract
Dynamic typing extends statically typed languages with a universal datatype, simplifying programs which must manipulate other programs as data, such as distributed, persistent, interpretive and generic programs. Current approaches, however, limit the use of polymorphism in dynamic values, and can be syntactically awkward.We introduce a new approach to dynamic typing, based on staged computation, which allows a single type-reconstruction algorithm to execute partly at compile time and partly at run-time. This approach seamlessly extends a single type system to accommodate types that are only known at run-time, while still supporting both type inference and polymorphism. The system is significantly more expressive than other approaches. Furthermore it can be implemented efficiently; most of the type inference is done at compile-time, leaving only some residual unification for run-time.We demonstrate our approach by examples in a small polymorphic functional language, and present its type system, type reconstruction algorithm, and operational semantics. Our proposal could also be readily adapted to many other programming languages.
Mark Shields, Tim Sheard, Simon L. Peyton Jones
POPL3
1998 Algorithms + Strategy = Parallelism
abstract
The process of writing large parallel programs is complicated by the need to specify both the parallel behaviour of the program and the algorithm that is to be used to compute its result. This paper introduces evaluation strategies : lazy higher-order functions that control the parallel evaluation of non-strict functional languages. Using evaluation strategies, it is possible to achieve a clean separation between algorithmic and behavioural code. The result is enhanced clarity and shorter parallel programs. Evaluation strategies are a very general concept: this paper shows how they can be used to model a wide range of commonly used programming paradigms, including divide-and-conquer parallelism, pipeline parallelism, producer/consumer parallelism, and data-oriented parallelism. Because they are based on unrestricted higher-order functions, they can also capture irregular parallel structures. Evaluation strategies are not just of theoretical interest: they have evolved out of our experience in parallelising several large-scale parallel applications, where they have proved invaluable in helping to manage the complexities of parallel behaviour. Some of these applications are described in detail here. The largest application we have studied to date, Lolita, is a 40,000 line natural language engineering system. Initial results show that for these programs we can achieve acceptable parallel performance, for relatively little programming effort.
Philip W. Trinder, Kevin Hammond, Hans-Wolfgang Loidl, Simon L. Peyton Jones
J. Funct. Program.4
1998 A Transformation-Based Optimiser for Haskell
Simon L. Peyton Jones, André L. M. Santos
Sci. Comput. Program.1
1997 Formally Based Profiling for Higher-Order Functional Languages
abstract
We present the first source-level profiler for a compiled, nonstrict, higher-order, purely functional language capable of measuring time as well as space usage. Our profiler is implemented in a production-quality optimizing compiler for Haskell and can successfully profile large applications. A unique feature of our approach is that we give a formal specification of the attribution of execution costs to cost centers. This specification enables us to discuss our design decisions in a precise framework, prove properties about the attribution of costs, and examine to effects of different program transformations on the attribution of costs. Since it is not obvious how to map this specification onto a particular implementation, we also present an implementation-oriented operational semantics, and prove it equivalent to the specification.
Patrick M. Sansom, Simon L. Peyton Jones
ACM Trans. Program. Lang. Syst.2
1996 Compiling Haskell by Program Transformation: A Report from the Trenches
Simon L. Peyton Jones
ESOP1
1996 Let-floating: Moving Bindings to Give Faster Programs
abstract
Virtually every compiler performs transformations on the program it is compiling in an attempt to improve efficiency. Despite their importance, however, there have been few systematic attempts to categorise such transformations and measure their impact.In this paper we describe a particular group of transformations --- the "let-floating" transformations --- and give detailed measurements of their effect in an optimizing compiler for the non-strict functional language Haskell. Let-floating has not received much explicit attention in the past, but our measurements show that it is an important group of transformations (at least for lazy languages), offering a reduction of more than 30% in heap allocation and 15% in execution time.
Simon L. Peyton Jones, Will Partain, André L. M. Santos
ICFP1
1996 GUM: A Portable Parallel Implementation of Haskell
abstract
GUM is a portable, parallel implementation of the Haskell functional language. Despite sustained research interest in parallel functional programming, GUM is one of the first such systems to be made publicly available.GUM is message-based, and portability is facilitated by using the PVM communications harness that is available on many multi-processors. As a result, GUM is available for both shared-memory (Sun SPARCserver multiprocessors) and distributed-memory (networks of workstations) architectures. The high message-latency of distributed machines is ameliorated by sending messages asynchronously, and by sending large packets of related data in each message.Initial performance figures demonstrate absolute speedups relative to the best sequential compiler technology. To improve the performance of a parallel Haskell program GUM provides tools for monitoring and visualising the behaviour of threads and of processors during execution.
Philip W. Trinder, Kevin Hammond, James S. Mattson Jr., Andrew S. Partridge, Simon L. Peyton Jones
PLDI5
1996 Concurrent Haskell
abstract
No abstract available.
Simon L. Peyton Jones, Andrew D. Gordon 0001, Sigbjørn Finne
POPL1
1996 Type Classes in Haskell
abstract
This article defines a set of type inference rules for resolving overloading introduced by type classes, as used in the functional programming language Haskell. Programs including type classes are transformed into ones which may be typed by standard Hindley-Milner inference rules. In contrast to other work on type classes, the rules presented here relate directly to Haskell programs. An innovative aspect of this work is the use of second-order lambda calculus to record type information in the transformed program.
Cordelia V. Hall, Kevin Hammond, Simon L. Peyton Jones, Philip Wadler
ACM Trans. Program. Lang. Syst.3
1995 Time and Space Profiling for Non-Strict Higher-Order Functional Languages
abstract
We present the first profiler for a compiled, non-strict, higher-order, purely functional language capable of measuring time as well as space usage. Our profiler is implemented in a production-quality optimising compiler for Haskell, has low overheads, and can successfully profile large applications.
Patrick M. Sansom, Simon L. Peyton Jones
POPL2
1994 Type Classes in Haskell
Cordelia V. Hall, Kevin Hammond, Simon L. Peyton Jones, Philip Wadler
ESOP3
1994 Lazy Funtional State Threads: An Abstract
John Launchbury, Simon L. Peyton Jones
ICLP2
1994 Lazy Functional State Threads
abstract
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.
John Launchbury, Simon L. Peyton Jones
PLDI2
1994 On the Equivalence Between CMC and TIM
abstract
Abstract In this paper we present an equivalence between TIM, a machine developed to implement non-strict functional programming languages, and the set of Categorical Multi-Combinators, a rewriting system developed with similar aims. These two models of computation at first appear to be quite different, but we show a direct equivalence between them, thereby adding some new structure to the ‘design-space’ of abstract machines for non-strict languages.
Rafael Dueire Lins, Simon J. Thompson, Simon L. Peyton Jones
J. Funct. Program.3
1993 Imperative Functional Programming
abstract
We present a new model, based on monads, for performing input/output in a non-strict, purely functional language. It is composable, extensible, efficient, requires no extensions to the type system, and extends smoothly to incorporate mixed-language working and in-place array updates.
Simon L. Peyton Jones, Philip Wadler
POPL1
1992 Implementing Lazy Functional Languages on Stock Hardware: The Spineless Tagless G-Machine
abstract
Abstract The Spineless Tagless G-machine is an abstract machine designed to support non-strict higher-order functional languages. This presentation of the machine falls into three parts. Firstly, we give a general discussion of the design issues involved in implementing non-strict functional languages. Next, we present the STG language , an austere but recognizably-functional language, which as well as a denotational meaning has a well-defined operational semantics. The STG language is the ‘abstract machine code’ for the Spineless Tagless G-machine. Lastly, we discuss the mapping of the STG language onto stock hardware. The success of an abstract machine model depends largely on how efficient this mapping can be made, though this topic is often relegated to a short section. Instead, we give a detailed discussion of the design issues and the choices we have made. Our principal target is the C language, treating the C compiler as a portable assembler.
Simon L. Peyton Jones
J. Funct. Program.1
1991 A Modular Fully-lazy Lambda Lifter in HASKELL
abstract
Abstract An important step in many compilers for functional languages is lambda lifting. In his thesis, Hughes showed that by doing lambda lifting in a particular way, a useful property called full laziness can be preserved. Full laziness has been seen as intertwined with lambda lifting ever since. We show that, on the contrary, full laziness can be regarded as a completely separate process to lambda lifting, thus making it easy to use different lambda lifters following a full‐laziness transformation, or to use the full‐laziness transformation in compilers which do not require lambda lifting. On the way, we present the complete code for our modular fully‐lazy lambda lifter, written in the HASKELL functional programming language.
Simon L. Peyton Jones, David R. Lester
Softw. Pract. Exp.1
1989 Parallel Implementations of Functional Programming Languages
abstract
One of the most attractive features of functional programming languages is their suitability for programming parallel computers. This paper is devoted to discussion of such a claim. Firstly, parallel functional programming is discussed from the programmer's point of view. Secondly, since most parallel functional language implementations are based on the concept of graph reduction, the issues raised by graph reduction are discussed. Finally, the paper concludes with a case study of a particular parallel graph reduction machine and a survey of other parallel architectures.
Simon L. Peyton Jones
Comput. J.1
1988 A Safe Approach to Parallel Combinator Reduction
Chris Hankin, Geoffrey Livingston Burn, Simon L. Peyton Jones
Theor. Comput. Sci.3
1986 A Safe Approach to Parallel Combinator Reduction (Extended Abstract)
Chris Hankin, Geoffrey Livingston Burn, Simon L. Peyton Jones
ESOP3
1985 Yacc in Sasl-an Exercise in Functional Programming
abstract
Abstract Among the advantages claimed for a purely functional programming style is ease of designing and implementing large programs. However, little experience of actually doing so has been gained so far. The experience of writing a particular medium sized program in a functional language is described here, with particular emphasis on the differences in programming style that were appropriate. This is compared with the experience of writing a very similar program in an imperative language. The main conclusions appear to be that the functional version was significantly easier to write, and was considerably smaller, though not by as large a factor as is sometimes claimed; that strong typing is, if anything, more desirable than in imperative systems; and that the question of debugging functional programs needs further research attention.
Simon L. Peyton Jones
Softw. Pract. Exp.1