# Ghostbuster: A Tool for Simplifying and Converting GADTs

Generalized Algebraic Datatypes, or simply GADTs, can encode non-trivial properties in the types of the constructors. Once such properties are encoded in a datatype, however, all code manipulating that datatype must provide proof that it maintains these properties in order to typecheck. In this paper, we take a step towards gradualizing these obligations. We introduce a tool, Ghostbuster, that produces simplified versions of GADTs which elide selected type parameters, thereby weakening the guarantees of the simplified datatype in exchange for reducing the obligations necessary to manipulate it. Like ornaments, these simplified datatypes preserve the recursive structure of the original, but unlike ornaments we focus on information-preserving bidirectional transformations. Ghostbuster generates type-safe conversion functions between the original and simplified datatypes, which we prove are the identity function when composed. We evaluate a prototype tool for Haskell against thousands of GADTs found on the Hackage package database, generating simpler Haskell'98 datatypes and round-trip conversion functions between the two.

#### Trevor L. McDonell

September 21, 2016

## Transcript

1. ### Ghostbuster: A Tool for Simplifying and Converting GADTs Trevor L.

McDonell 3 1 Timothy A. K. Zakian 3 2 Matteo Cimini 3 Ryan R. Newton 3 1University of New South Wales 2University of Oxford 3Indiana University tmcdonell
2. ### we should teach our students parallelism from the outset! end

of Moore’s rule, blah blah blah…
3. None
4. None

datatypes

10. ### data List a where Nil :: List a Cons ::

a -> List a -> List a head :: List a -> a head Nil = ): simply typed ADTs
11. ### data List a where Nil :: List a Cons ::

a -> List a -> List a head :: List a -> a head Nil = ): type-indexed GADTs simply typed ADTs data Vec n a where VNil :: Vec Zero a VCons :: a -> Vec n a -> Vec (Succ n) a vhead :: Vec (Succ n) a -> a vhead VNil ^_^

13. ### type-indexed GADTs new feature? Diﬃculties… - rapid prototyping - missing

compiler features - … error messages

18. ### new feature type-indexed GADTs simply typed ADTs remove type invariants

reestablish invariants
19. ### new feature type-indexed GADTs simply typed ADTs remove type invariants

reestablish invariants focus of this work

in the wild:

25. ### data List a where Nil :: List a Cons ::

a -> List a -> List a
26. ### data Vec n a where VNil :: Vec Zero a

VCons :: a -> Vec n a -> Vec (Succ n) a data List a where Nil :: List a Cons :: a -> List a -> List a
27. ### data Vec n a where VNil :: Vec Zero a

VCons :: a -> Vec n a -> Vec (Succ n) a data List a where Nil :: List a Cons :: a -> List a -> List a ( Ornaments, McBride 2010 ) ( Dagand, ICFP 2016 )
28. ### data Vec n a where VNil :: Vec Zero a

VCons :: a -> Vec n a -> Vec (Succ n) a
29. ### data Vec n a where VNil :: Vec Zero a

VCons :: a -> Vec n a -> Vec (Succ n) a {-# Ghostbuster: synthesize n # -}
30. ### data Vec n a where VNil :: Vec Zero a

VCons :: a -> Vec n a -> Vec (Succ n) a data Vec' a where VNil' :: Vec' a VCons' :: a -> Vec' a -> Vec' a {-# Ghostbuster: synthesize n # -} upVec downVec
31. ### instance … => Read (Vec n a) where readsPrec i

s =

where readsPrec i s = [ (v,r) | (v',r) <- readsPrec i s

Read (Vec n a) where readsPrec i s = [ (v,r) | (v',r) <- readsPrec i s , let Just v = downVec v' ]
34. ### data List a where Nil :: List a Cons ::

a -> List a -> List a {-# Ghostbuster: synthesize a # -}
35. ### data List a where Nil :: List a Cons ::

a -> List a -> List a {-# Ghostbuster: synthesize a # -}
36. ### data List a where Nil :: List a Cons ::

a -> List a -> List a {-# Ghostbuster: check a # -}
37. ### data List a where Nil :: List a Cons ::

a -> List a -> List a {-# Ghostbuster: check a # -} data List' where Nil' :: List' Cons' :: ∃ a. TypeRep a -> a -> List' -> List'
38. ### data List a where Nil :: List a Cons ::

a -> List a -> List a {-# Ghostbuster: check a # -} data List' where Nil' :: List' Cons' :: ∃ a. TypeRep a -> a -> List' -> List' runtime type checks
39. ### data List a where Nil :: List a Cons ::

a -> List a -> List a {-# Ghostbuster: check a # -} data List' where Nil' :: List' Cons' :: ∃ a. TypeRep a -> a -> List' -> List' upList downList runtime type checks
40. ### checked vs. synthesised an information-ﬂow criterion for how erased type

information can be recovered
41. ### checked vs. synthesised {-# synthesize n # -} downVec ::

Vec' a -> Maybe (Vec n a)
42. ### checked vs. synthesised output: determined by structure of the datatype

{-# synthesize n # -} downVec :: Vec' a -> Maybe (Vec n a)
43. ### checked vs. synthesised output: determined by structure of the datatype

{-# synthesize n # -} downVec :: Vec' a -> Maybe (Vec n a) downVec = openVecS . downVecS
44. ### checked vs. synthesised output: determined by structure of the datatype

{-# synthesize n # -} downVec :: Vec' a -> Maybe (Vec n a) keep synthesized type existential downVec = openVecS . downVecS
45. ### checked vs. synthesised output: determined by structure of the datatype

{-# synthesize n # -} downVec :: Vec' a -> Maybe (Vec n a) keep synthesized type existential downVec = openVecS . downVecS data SVec a where SVec :: ∃ n. Vec n a -> SVec a downVecS :: Vec' a -> SVec a
46. ### checked vs. synthesised output: determined by structure of the datatype

{-# synthesize n # -} downVec :: Vec' a -> Maybe (Vec n a) keep synthesized type existential expose the existential downVec = openVecS . downVecS data SVec a where SVec :: ∃ n. Vec n a -> SVec a downVecS :: Vec' a -> SVec a openVecS :: SVec a -> Maybe (Vec n a)
47. ### checked vs. synthesised output: determined by structure of the datatype

{-# synthesize n # -} downVec :: Vec' a -> Maybe (Vec n a) keep synthesized type existential expose the existential downVec = openVecS . downVecS data SVec a where SVec :: ∃ n. Vec n a -> SVec a downVecS :: Vec' a -> SVec a openVecS :: SVec a -> Maybe (Vec n a) withVecS :: SVec a -> (∀ n. Vec n a -> b) -> b
48. ### checked vs. synthesised output: determined by structure of the datatype

{-# synthesize n # -} downVec :: Vec' a -> Maybe (Vec n a)
49. ### checked vs. synthesised output: determined by structure of the datatype

{-# synthesize n # -} downVec :: Vec' a -> Maybe (Vec n a) {-# check a # -} downList :: List' -> Maybe (List a)
50. ### checked vs. synthesised output: determined by structure of the datatype

{-# synthesize n # -} downVec :: Vec' a -> Maybe (Vec n a) input: must check the type of each element {-# check a # -} downList :: List' -> Maybe (List a)