GenericPretty: A generic, derivable, haskell pretty printer.

[ bsd3, generics, library, pretty-printer, text ] [ Propose Tags ]
  • GenericPretty is a haskell library that provides support for automatic derivation of pretty printing functions on user defined data types.

  • The Pretty library http://www.haskell.org/ghc/docs/7.0.4/html/libraries/ghc-7.0.4/Pretty.html is used underneath, the work is done over Pretty.Doc types. The library MyPretty is also provided. This library is a thin wrapper around the Pretty library and implements only Style related features. These features are planned to be added to the Pretty library itself. When that happens MyPretty will become obsolete and will be replaced by Pretty.

  • The output provided by the library functions is identical to that of Prelude.show, except it has extra whitespace.

  • This package requires the use of the new GHC.Generics features: http://www.haskell.org/haskellwiki/Generics. These features are present in versions of GHC >= 7.2.

  • The Generics used are based on those described in the paper "A Generic Deriving Mechanism for Haskell" - by Magalhaes, Dijkstra, Jeuring and Loh in Proceedings of the third ACM Haskell symposium on Haskell (Haskell'2010), pp. 37-48, ACM, 2010: http://dreixel.net/research/pdf/gdmh.pdf There are several changes from the original paper in the ghc implementation which are described here: http://www.haskell.org/haskellwiki/Generics#Changes_from_the_paper.

  • This generics mechanism supports deriving for all haskell datatypes EXCEPT for constrained datatypes. That is to say, datatypes which have a context will fail.

For instance,

"data (Eq a) => Constr a = Constr a"

will fail because of the (Eq a) context.

  • Installation instructions

The package is installed in the same way as any other package. If needed, instructions are provided below.

  1. Make sure you have a version of ghc >= 7.2 installed and that you can use the runhaskell command from the command line.

  2. Download the file "GenericPretty-1.1.2.tar.gz" from this page.

  3. Unpack the file. If using a UNIX system, run

tar xzf GenericPretty-1.1.2.tar.gz

If on windows use your preferred unpacking utility(for instance, 7zip : http://www.7-zip.org/)

  1. Move to the correct directory:

cd GenericPretty-1.1.2

  1. Run the following haskell commands to install the library globally

runhaskell Setup configure

runhaskell Setup build

runhaskell Setup install

If something went wrong, you can check this page for more info, look at manual installation: http://www.haskell.org/haskellwiki/Cabal/How_to_install_a_Cabal_package

  • Basic example of usage

Here is a source file demonstrating the GenericPretty usage

import Text.PrettyPrint.GenericPretty

data Tree a = Leaf a | Node (Tree a) (Tree a) deriving (Generic)

instance (Out a) => Out (Tree a) where docPrec = genOut

tree :: Tree Int

tree = Node (Node (Leaf 333333333) (Leaf (-555555555))) (Leaf 777777777)

main = pp tree

  • For the above program to run the -XDeriveGeneric flag needs to be set.

This can be done either directly at the command line, by compiling with "ghc -XDeriveGeneric" or in the source code by using the LANGUAGE pragma (it seems I can't demonstrate the LANGUAGE pragma since cabal hates special characters. An example however is provided in the README file included in the package). Alternatively, for more information on the LANGUAGE pragma see here: http://www.haskell.org/ghc/docs/7.0.4/html/users_guide/pragmas.html

Besides setting the flag, one must derive Generic for the desired datatype by typing "deriving (Generic)" and write an instance of Out defining docPrec as "docPrec = genOut". Then the pretty printing functions such as "pp" can be used on any data of that type.

For more details about the above example as well as examples of customizing the pretty printing please check the README file included in the package. For more information about the library itself and what it exports check the API linked further down this page.


[Skip to Readme]

Modules

[Last Documentation]

  • Text
    • PrettyPrint
      • Text.PrettyPrint.GenericPretty
      • Text.PrettyPrint.MyPretty

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 0.1.0, 0.1.1, 0.1.2, 0.1.3, 1.0.0, 1.0.1, 1.1.0, 1.1.1, 1.1.2, 1.1.3, 1.1.4, 1.1.5, 1.1.6, 1.1.7, 1.1.8, 1.1.9, 1.2.0, 1.2.1, 1.2.2
Dependencies base (>=3 && <5), ghc (>=7.2), ghc-prim [details]
License BSD-3-Clause
Author Razvan Ranca
Maintainer ranca.razvan@gmail.com
Category Text, Generics, Pretty Printer
Home page https://github.com/HaggisMcMutton/GenericPretty
Source repo head: git clone git@github.com:HaggisMcMutton/GenericPretty.git
Uploaded by RazvanRanca at 2011-08-11T23:00:09Z
Distributions LTSHaskell:1.2.2, NixOS:1.2.2, Stackage:1.2.2
Reverse Dependencies 18 direct, 14 indirect [details]
Downloads 20709 total (63 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs not available [build log]
Last success reported on 2015-12-07 [all 8 reports]

Readme for GenericPretty-1.1.2

[back to package description]
*******************************************************************************
*     GenericPretty. 
*     A Generic, Derivable, Haskell Pretty Printer
*******************************************************************************

========================== Description ========================================

GenericPretty is a haskell library that provides support for automatic
derivation of pretty printing functions on user defined data types.

The Pretty library [1] is used underneath, the work is over 'Pretty.Doc' types.

The library "MyPretty" is also provided. This library is a thin wrapper around 
the "Pretty" library and implements only "Style" related features. 
These features are planned to be added to the Pretty library itself. When 
that happens "MyPretty" will become obsolete and will be replaced by "Pretty".
  
The output provided by the library functions is identical to that of 
Prelude.show, except it has extra whitespace.
	
This library requires the use of the new GHC.Generics features [2]
These features are present in versions of GHC >= 7.2.

The Generics used are based on those described in the paper "A Generic Deriving
Mechanism for Haskell" - by Magalh�es, Dijkstra, Jeuring and L�h in Proceedings
of the third ACM Haskell symposium on Haskell (Haskell'2010), pp. 37�48, ACM, 
2010 [3]. 
There are however several changes between the mechanism described in 
the paper and the one implemented in GHC [4].

This generics mechanism supports deriving for all haskell datatypes EXCEPT for
constrained datatypes.
That is to say, datatypes which have a context will fail. For instance,
"data (Eq a) => Constr a = Constr a" will fail because of the (Eq a) context.

============================== Basic Example ==================================

Here is a haskell source file, called 'SimpleTest.hs'
----------------------------------------------------
{-# LANGUAGE DeriveGeneric #-}

import Text.PrettyPrint.GenericPretty

data Tree a = Leaf a | Node (Tree a) (Tree a) deriving (Generic)

instance (Out a) => Out (Tree a) where
	docPrec = genOut

tree1 :: Tree Int
tree1 = Node (Node (Leaf 333333) (Leaf (-555555)))(Node (Node(Node(Leaf 888888) 
		(Leaf 57575757))(Leaf (-14141414)))(Leaf 7777777))
			
main = pp tree1
------------------------------------------------
The flag DeriveGeneric must be given to GHC. This can be done as above, 
in a 'LANGUAGE' pragma, or manually by compiling with 'ghc -XDeriveGeneric'.

As can be seen, to use the library one must simply import it, derive 'Generic' 
on the custom data type, and write an instance of 'Out' using 'genOut'.

Then one can use the pretty printing functions, such as 'pp' and 'pretty'.

Compiling and running the file is simple and gives the following result.
-----------------------------
$ ghc SimpleTest.hs
$ SimpleTest

Node (Node (Leaf 333333) (Leaf (-555555)))
     (Node (Node (Node (Leaf 888888) (Leaf 57575757))
                 (Leaf (-14141414)))
           (Leaf 7777777))
---------------------------
If we replaced the main function with 'main = ppLen 30 tree1', 
the result would instead be:

-----------------------------
Node (Node (Leaf 333333)
           (Leaf (-555555)))
     (Node (Node (Node (Leaf 888888)
                       (Leaf 57575757))
                 (Leaf (-14141414)))
           (Leaf 7777777))
-------------------------------
In this case the output tries to remain under 30 characters/line, if possible, 
while always maintaining correct indentation.

There also is a 'ppStyle' function which lets you further customize the output
by giving a 'Style' which consists of the line length, the number of ribbons 
per line and the mode to use.

A ribbon length is the length of non-indentation text per line.
So if I used a line length of 80 and 2 ribbons per line than I would have a
maximum of 40 non-indentation characters on any line.

The mode tells 'Pretty' how to render the result. There are 4 options:
1. PageMode - the default rendering
2. ZigZagMode - zig-zag cuts
3. LeftMode - there is no indentation and no maximum line length
4. OneLineMode - everything is put on one line	

The most interesting one is the ZigZagMode. Using the running example we write:

--------------------------------------
{-# LANGUAGE DeriveGeneric #-}

import Text.PrettyPrint.GenericPretty
import Text.PrettyPrint.MyPretty

data Tree a = Leaf a | Node (Tree a) (Tree a) deriving (Generic)

instance (Out a) => Out (Tree a) where
	docPrec = genOut

tree1 :: Tree Int
tree1 = Node (Node (Leaf 333333) (Leaf (-555555)))(Node (Node(Node(Leaf 888888) 
		(Leaf 57575757))(Leaf (-14141414)))(Leaf 7777777))
			
zigStyle :: Style
zigStyle = Style {mode = ZigZagMode, lineLength = 30, ribbonsPerLine = 1.5}

main = ppStyle zigStyle tree1
--------------------------------------
We import "MyPretty" to gain access to the "Style" functionality.

Running the program, we get:
-------------------------------------
Node (Node (Leaf 333333)

/////
      (Leaf (-555555)))
(Node (Node (Node (Leaf 888888)

/////
             (Leaf 57575757))
       (Leaf (-14141414)))
 (Leaf 7777777))
-------------------------------------
Notice that the "/" show us the direction in which the rows below have been moved
(left in this case) and the number of "/"s indicate the number of characters
that the rows were moved(in this case 5 characters to the left)

========================== Customization Example ==============================

While the previous approach provides us some with some options as to the format
of the pretty printed result, sometimes you need even more control.

Fully customizing the pretty printed results is straightforward, as in the
following example called 'CustomTest.hs'
----------------------------
{-# LANGUAGE DeriveGeneric #-}

import Text.PrettyPrint.GenericPretty
import Text.PrettyPrint.MyPretty

data Tree a = Leaf a | Node (Tree a) (Tree a) deriving (Generic)

instance (Out a) => Out (Tree a) where
  doc (Leaf a) =  parens $ text "customLeaf" <+> doc a
  doc (Node a b) = parens $ text "customNode" $$ nest 1 (doc a) 
                                                    $$ nest 1 (doc b)

tree1 :: Tree Int
tree1 = Node (Node (Leaf 333333) (Leaf (-555555)))(Node (Node(Node(Leaf 888888) 
		(Leaf 57575757))(Leaf (-14141414)))(Leaf 7777777))
			
main = pp tree1
------------------------------
Here we import the library 'MyPretty' and use it directly to define doc.
We could have manually defined 'docPrec' or 'docList' as well if we wanted. As
it is now they are inferred from our definition of doc.

The syntax used in the definition is the one used in both the Pretty[1] and the
Text.PrettyPrint.HughesPJ [5] libraries.(the second is better documented).

By running the above we get a tree with a minimum of indentation:
-----------------------------------
(customNode
  (customNode
    (customLeaf 333333)
    (customLeaf -555555))
  (customNode
    (customNode
      (customNode
        (customLeaf 888888)
        (customLeaf 57575757))
      (customLeaf -14141414))
    (customLeaf 7777777)))

-----------------------------------

========================= Further Info ========================================

The above 'Tree' examples can be found in 'TestSuite/SimpleTest.hs',
'TestSuite/CustomTest.hs' and 'TestSuite.ZigZagTest.hs'. More involved examples
integrated with QuickCheck can be found in 'TestSuite/Tests.hs'.

Further information can be found in the API [6] and in the source code itself.

============================ Contact ==========================================

Please send any questions/suggestions to:
Razvan Ranca <ranca.razvan@gmail.com>

============================= Links ===========================================

[1] http://www.haskell.org/ghc/docs/7.0.4/html/libraries/ghc-7.0.4/Pretty.html
[2] http://www.haskell.org/haskellwiki/Generics
[3] http://dreixel.net/research/pdf/gdmh.pdf
[4] http://www.haskell.org/haskellwiki/Generics#Changes_from_the_paper
[5] http://hackage.haskell.org/packages/archive/pretty/1.1.0.0/doc/html/Text-PrettyPrint-HughesPJ.html
[6] http://hackage.haskell.org/packages/archive/GenericPretty/1.0.1/doc/html/Text-PrettyPrint-GenericPretty.html