RepLib-0.2.1: examples/Main.hs
-- OPTIONS -fglasgow-exts -fth -fallow-undecidable-instances
{-# LANGUAGE TemplateHaskell, UndecidableInstances, ScopedTypeVariables, FlexibleInstances, MultiParamTypeClasses #-}
-----------------------------------------------------------------------------
-- |
-- Module : Main
-- Copyright : (c) The University of Pennsylvania, 2006
-- License : BSD
--
-- Maintainer : sweirich@cis.upenn.edu
-- Stability : experimental
-- Portability : non-portable
--
-- A file demonstrating the use of RepLib
--
-----------------------------------------------------------------------------
module Main where
import Data.RepLib
import Language.Haskell.TH
-- For each datatype that we define, we need to also create its representation.
-- The template Haskell function derive does this automatically for
-- each type.
data Tree a = Leaf a | Node (Tree a) (Tree a)
$(derive [''Tree])
data Day = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday
$(derive [''Day])
-- Note, for mutually recursive datatypes, use "derive" and give list
-- of type names.
-- Note also that the functions of RepLib can cooperate with the
-- traditional 'deriving' mechanism
data Company = C [Dept] deriving (Eq, Ord, Show)
data Dept = D String Manager [CUnit] deriving (Eq, Ord, Show)
data Manager = M Employee deriving (Eq, Ord, Show)
data CUnit = PU Employee | DU Dept deriving (Eq, Ord, Show)
data Employee = E Person Salary deriving (Eq, Ord, Show)
data Person = P String deriving (Eq, Ord, Show)
data Salary = S Float deriving (Eq, Ord, Show)
$(derive
[''Company,
''Dept,
''CUnit,
''Employee,
''Manager,
''Person,
''Salary])
--
-- Some sample data for these types
--
t1 :: Tree Int
t1 = Node (Node (Leaf 3) (Leaf 4)) (Node (Leaf 5) (Leaf 6))
t2 :: Tree Int
t2 = Node (Node (Leaf 0) (Leaf 7)) (Leaf 20)
s1 :: Company
s1 = C [D "Types" (M (E (P "Stephanie") (S 1000.0)))
[PU (E (P "Michael") (S 50)),
PU (E (P "Samuel") (S 50)),
PU (E (P "Theodore") (S 50))],
D "Terms" (M (E (P "Stephanie") (S 200)))
[DU (D "Shipping" (M (E (P "Alice") (S 3000)))
[])]]
--
-- Prelude operations.
--
-- Note that we didn't derive Eq, Ord, Bounded or Show for "Day" and "Tree". We can
-- do that now with operations from RepLib.PreludeLib.
-- for Day
instance Eq Day where
(==) = eqR1 rep1
instance Ord Day where
compare = compareR1 rep1
instance Bounded Day where
minBound = minBoundR1 rep1
maxBound = maxBoundR1 rep1
instance Show Day where
showsPrec = showsPrecR1 rep1
-- for Tree
instance (Rep a, Eq a) => Eq (Tree a) where (==) = eqR1 rep1
instance (Rep a, Show a) => Show (Tree a) where showsPrec = showsPrecR1 rep1
instance (Rep a, Ord a) => Ord (Tree a) where compare = compareR1 rep1
-- Besides the prelude operations, RepLib provides a number of other
-- type-indexed operations.
--
-- Instances for RepLib.Lib operations
--
-- Generate creates arbitrary elements of a type, up to a certain depth.
instance Generate Day
instance Generate a => Generate (Tree a)
instance Generate Company
instance Generate Dept
instance Generate Manager
instance Generate CUnit
instance Generate Employee
instance Generate Person
instance Generate Salary
-- Sum adds together all of the Ints in a datastructure
instance GSum a => GSum (Tree a)
instance GSum Company
instance GSum Dept
instance GSum Manager
instance GSum CUnit
instance GSum Employee
instance GSum Person
instance GSum Salary
-- Shrink creates smaller versions of a data structure.
instance Shrink a => Shrink (Tree a)
--
-- SYB Style operations
--
-- RepLib also supports many of the combinators from the SYB library. For example,
-- we can include the following code from the "Paradise" benchmark that gives everyone
-- in the company a raise.
-- Increase salary by percentage
increase :: Float -> Company -> Company
increase k = everywhere (mkT (incS k))
-- "interesting" code for increase
incS :: Float -> Salary -> Salary
incS k (S s) = S (s * (1+k))
--
-- Generalized folds
--
-- finally, we define generalized versions of fold left and
-- fold right for the Tree type constructor.
instance Fold Tree where
foldRight op = rreduceR1 (rTree1 (RreduceD { rreduceD = op })
(RreduceD { rreduceD = foldRight op}))
foldLeft op = lreduceR1 (rTree1 (LreduceD { lreduceD = op })
(LreduceD { lreduceD = foldLeft op }))
main = do print (minBound :: Day)
print (maxBound :: Day)
print t1
print s1
print (Monday < Tuesday)
print (t1 < t2)
--
print (generate 7 :: [Day])
print (generate 3 :: [Tree Int])
print (generate 7 :: [Company])
--
print (subtrees t1)
print (gsum t1)
print (gsum t2)
--
print (increase 0.1 s1)
print (s1 < (increase 0.2 s1))
--
print (gproduct t1)
print (count t1)