
Total Haskell is Reasonable Coq Antal Spector-Zabusky Joachim Breitner Christine Rizkallah Stephanie Weirich {antals,joachim,criz,sweirich}@cis.upenn.edu University of Pennsylvania Philadelphia, PA, USA Abstract However, Haskell programmers typically reason about We would like to use the Coq proof assistant to mechan- their code only informally. Most proofs are done on paper, ically verify properties of Haskell programs. To that end, by hand, which is tedious, error-prone, and does not scale. we present a tool, named hs-to-coq, that translates total On the other hand, the Coq proof assistant [22] is a great Haskell programs into Coq programs via a shallow embed- tool for writing proofs. It allows programmers to reason ding. We apply our tool in three case studies – a lawful Monad about total functional programs conveniently, efficiently, and instance, “Hutton’s razor”, and an existing data structure li- with high confidence. However, Coq lacks GHC’s extensive brary – and prove their correctness. These examples show ecosystem for program development. that this approach is viable: both that hs-to-coq applies Therefore, we propose a multimodal approach to the veri- to existing Haskell code, and that the output it produces is fication of total functional programs: write code in Haskell amenable to verification. and prove it correct in Coq. To support this plan, we have developed an automatic translator, called hs-to-coq, that CCS Concepts • Software and its engineering → Soft- allows this approach to scale. ware verification; For example, consider the standard map function on lists Keywords Coq, Haskell, verification (from the Haskell Prelude), and the list Functor instance. ACM Reference Format: map :: ¹a -> bº -> »a¼ -> »b¼ Antal Spector-Zabusky, Joachim Breitner, Christine Rizkallah, and map f » ¼ = » ¼ Stephanie Weirich. 2018. Total Haskell is Reasonable Coq. In Pro- map f ¹x : xsº = f x : map f xs ceedings of 7th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP’18). ACM, New York, NY, USA, 14 pages. instance Functor » ¼ where fmap = map https://doi.org/10.1145/3167092 Our tool translates this Haskell program automatically to the analogous Coq definitions. The map function becomes 1 Introduction the expected fixpoint. The Haskell programming language is a great tool for produc- ing pure, functional programs. Its type system tracks the use Definition map {a} {b} : ¹a -> bº -> list a -> list b := of impure features, such as mutation and IO, and its standard fix map arg_62__ arg_63__ library promotes the use of mathematically-inspired struc- := match arg_62__; arg_63__ with tures that have strong algebraic properties. At the same time, j ; nil => nil Haskell development is backed by an industrial-strength j f; cons x xs => cons ¹f xº ¹map f xsº end compiler (the Glasgow Haskell Compiler, GHC) [21], and . supported by mature software development tools, such as Similarly, the Functor type class in Haskell turns into a Coq IDEs and testing environments. type class of the same name, and Haskell’s Functor instance arXiv:1711.09286v1 [cs.PL] 25 Nov 2017 for lists becomes a type class instance on the Coq side. Once the Haskell definitions have been translated to Coq, users can prove theorems about them. For example, we pro- vide a type class for lawful functors: Class FunctorLaws ¹t : Type -> Typeº `{Functor t} := {functor_identity : forall a ¹x : t aº; fmap id x = x; CPP’18, January 8–9, 2018, Los Angeles, CA, USA functor_composition : © 2018 Copyright held by the owner/author(s). Publication rights licensed forall a b c ¹f : a -> bº ¹g : b -> cº ¹x : t aº; to the Association for Computing Machinery. This is the author’s version of the work. It is posted here for your personal fmap g ¹fmap f xº = fmap ¹g ◦ fº x} . use. Not for redistribution. The definitive Version of Record was published A list instance of the FunctorLaws type class is a formal in Proceedings of 7th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP’18), https://doi.org/10.1145/3167092. proof that the list type, using this definition of map, is a lawful functor. base-4.9.1.0: Basic libraries Source Contents Index Copyright (c) The University of Glasgow 2001 BSD-style (see the License file libraries/base /LICENSE) Maintainer [email protected] Stability provisional Portability portable Safe Trustworthy Haskell Language Haskell2010 Control.Monad The Functor, Monad and Contents MonadPlus Functor and monad classes classes, with Functions some useful Naming conventions operations Basic Monad functions on monads. Generalisations of list functions Conditional execution of monadic Functor expressions Monadic lifting operators and Strict monadic functions monad classes class Functor f where # Source The Functor class is used for types that can be mapped over. Instances of Functor should satisfy the following laws: fmap id == id fmap (f . g) == fmap f . fmap g The instances of Functor for lists, Maybe and IO satisfy these laws. Minimal complete definition fmap Methods fmap :: (a -> b) -> f a -> f b # Source Instances Functor [] # Functor Maybe # Functor IO # Functor V1 # Functor U1 # Functor Par1 # Functor ReadP # Functor ReadPrec # Functor Last # Functor First # Functor Product # Functor Sum # Functor Dual # Functor STM # Functor Handler # Functor ZipList # Functor ArgDescr # Functor OptDescr # Functor ArgOrder # Functor Complex # Functor NonEmpty # Functor Option # Functor Last # Functor First # Functor Max # Functor Min # Functor Identity # Functor ((->) r) # Functor (Either a) # Functor f => Functor (Rec1 f) # Functor (URec Char) # Functor (URec Double) # Functor (URec Float) # Functor (URec Int) # Functor (URec Word) # Functor (URec (Ptr ())) # Functor ((,) a) # Functor (ST s) # Functor (Proxy *) # Arrow a => Functor (ArrowMonad a) # Monad m => Functor (WrappedMonad m) # Functor (ST s) # Functor (Arg a) # Functor (K1 i c) # (Functor g, Functor f) => Functor ((:+:) f g) # (Functor g, Functor f) => Functor ((:*:) f g) # (Functor g, Functor f) => Functor ((:.:) f g) # Functor f => Functor (Alt * f) # Functor (Const * m) # Arrow a => Functor (WrappedArrow a b) # Functor f => Functor (M1 i c f) # (Functor f, Functor g) => Functor (Product * f g) # (Functor f, Functor g) => Functor (Sum * f g) # (Functor f, Functor g) => Functor (Compose * * f g) CPP’18, January 8–9, 2018, Los Angeles, CA, USA Spector-Zabusky, Breitner, Rizkallah, and Weirich # This process makes sense only for inductive data types class Applicative m => Monad m where # Source and total, terminating functions. This is where the semantics The Monad class defines the basic operations over a monad, of lazy and strict evaluation, and hence of Haskell and Coq, a concept from a branch of mathematics known as coincide [8]. However, the payoff is that a successful transla- category theory. From the perspective of a Haskell tion is itself a termination proof, even before other properties programmer, however, it is best to think of a monad as an have been shown. Furthermore, because Coq programs may abstract datatype of actions. Haskell's do expressions be evaluated (within Coq) or compiled (via extraction) these provide a convenient syntax for writing monadic properties apply, not to a formal model of computation, but expressions. to actual runnable code. Instances of Monad should satisfy the following laws: Our overarching goal is to make it easy for a Haskell pro- grammer to produce Coq versions of their programs that are return a >>= k = k a suitable for verification. The Coq rendition should closely m >>= return = m follow the Haskell code – the same names should be used, even within functions; types should be unaltered; abstrac- m >>= (\x -> k x >>= h) = (m >>= k) >>= h tions like type classes and modules should be preserved – so that the programmer obtains not just a black-box that hap- Furthermore, the Monad and Applicative operations pens to do the same thing as the original Haskell program, should relate as follows: but a live Coq version of the input. pure = return Furthermore, the development environment should in- clude as much as possible of total Haskell. In particular, pro- (<*>) = ap grammers should have access to standard libraries and lan- The above laws imply: guage features and face few limitations other than totality. Figure 1. The documentation of the Monad type class lists Also, because programs often change, the generated Coq the threefmap monad f xs laws= xs and >>= thereturn two . laws f relating it to must be usable directly, or with declarative modifications, so Applicative (screenshot).2 that the proofs can evolve with the program. (>>) = (*>) Conversely, an additional application of hs-to-coq is as 2 Reasoning About Haskell Code in Coq a Haskell “rapid prototyping front-end” for Coq. A poten- tial workflow is: (1) implement a program in Haskell first, We present and evaluate our approach to verifying Haskell in order to quickly develop and test it; (2) use hs-to-coq in three examples, all involving pre-existing Haskell code. 1 von 4 to translate it to the Coq world; and (3) extend and verify 2.1 Algebraic Laws the Coq output. This framework allows diverse groups of functional programmers and proof engineers to collaborate; Objective The Functor type class is not the only class with focusing on their areas of expertise. laws. Many Haskell programs feature structures that are not Therefore, in this paper, we describe the design and im- only instances of the Functor class, but also of Applicative plementation of the hs-to-coq tool and
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages14 Page
-
File Size-