quickspec-0.9.6: examples/PrettyPrinting.hs
{-# LANGUAGE DeriveDataTypeable, ScopedTypeVariables #-}
module Main where
import Control.Monad
import Data.Typeable
import Test.QuickCheck
import Test.QuickSpec
newtype Layout a = Layout [(Int, [a])] deriving (Typeable, Eq, Ord, Show)
instance Arbitrary a => Arbitrary (Layout a) where
arbitrary = fmap Layout (liftM2 (:) arbitrary arbitrary)
text :: [a] -> Layout a
text s = Layout [(0, s)]
nest :: Int -> Layout a -> Layout a
nest k (Layout l) = Layout [(i+k, s) | (i, s) <- l]
($$) :: Layout a -> Layout a -> Layout a
Layout xs $$ Layout ys = Layout (xs ++ ys)
(<>) :: Layout a -> Layout a -> Layout a
Layout xs <> Layout ys = f (init xs) (last xs) (head ys) (tail ys)
where f xs (i, s) (j, t) ys = Layout xs $$ Layout [(i, s ++ t)] $$ nest (i + length s - j) (Layout ys)
pretty :: forall a. (Typeable a, Ord a, Arbitrary a) => a -> [Sig]
pretty a = [
["d","e","f"] `vars` (undefined :: Layout a),
["s","t","u"] `vars` (undefined :: [a]),
["n","m","o"] `vars` (undefined :: Int),
"text" `fun1` (text :: [a] -> Layout a),
"nest" `fun2` (nest :: Int -> Layout a -> Layout a),
"$$" `fun2` (($$) :: Layout a -> Layout a -> Layout a),
"<>" `fun2` ((<>) :: Layout a -> Layout a -> Layout a),
background [
"[]" `fun0` ([] :: [a]),
"++" `fun2` ((++) :: [a] -> [a] -> [a]),
"0" `fun0` (0 :: Int),
"length" `fun1` (length :: [a] -> Int),
"+" `fun2` ((+) :: Int -> Int -> Int)]]
main = quickSpec (pretty (undefined :: Two))