home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Datafile PD-CD 3
/
PDCD_3.iso
/
utilities
/
utilsf
/
hugs
/
hs
/
evalred
< prev
next >
Wrap
Text File
|
1995-02-14
|
3KB
|
98 lines
-- This program can be used to solve exercise 1.2.1 in Bird & Wadler's
-- ``Introduction to functional programming'' ....
--
-- Write down the ways to reduce sqr (sqr (3+7)) to normal form
-- (without assuming shared evaluation of function arguments).
data Term = Square Term -- The square of a term
| Plus Term Term -- The sum of two terms
| Times Term Term -- The product of two terms
| Num Int -- A numeric constant
instance Text Term where
showsPrec p (Square t) = showString "sqr " . shows t
showsPrec p (Plus n m) = showChar '(' . shows n . showChar '+'
. shows m . showChar ')'
showsPrec p (Times n m) = showChar '(' . shows m . showChar '*'
. shows n . showChar ')'
showsPrec p (Num i) = shows i
-- What are the subterms of a given term?
type Subterm = (Term, -- The subterm expression
Term->Term) -- A function which embeds
-- it back in the original
-- term
rebuild :: Subterm -> Term
rebuild (t, embed) = embed t
subterms :: Term -> [Subterm]
subterms t = [ (t,id) ] ++ properSubterms t
properSubterms :: Term -> [Subterm]
properSubterms (Square t) = down Square (subterms t)
properSubterms (Plus t1 t2) = down (flip Plus t2) (subterms t1) ++
down (Plus t1) (subterms t2)
properSubterms (Times t1 t2) = down (flip Times t2) (subterms t1) ++
down (Times t1) (subterms t2)
properSubterms (Num n) = []
down :: (Term -> Term) -> [Subterm] -> [Subterm]
down f = map (\(t, e) -> (t, f.e))
-- Some (semi-)general variations on standard themes:
filter' :: (a -> Bool) -> [(a, b)] -> [(a, b)]
filter' p = filter (p.fst)
map' :: (a -> b) -> [(a, c)] -> [(b, c)]
map' f = map (\(a, c) -> (f a, c))
-- Reductions:
isRedex :: Term -> Bool
isRedex (Square _) = True
isRedex (Plus (Num _) (Num _)) = True
isRedex (Times (Num _) (Num _)) = True
isRedex _ = False
contract :: Term -> Term
contract (Square t) = Times t t
contract (Plus (Num n) (Num m)) = Num (n+m)
contract (Times (Num n) (Num m)) = Num (n*m)
contract _ = error "Not a redex!"
singleStep :: Term -> [Term]
singleStep = map rebuild . map' contract . filter' isRedex . subterms
normalForms :: Term -> [Term]
normalForms t
| null ts = [ t ]
| otherwise = [ n | t'<-ts, n<-normalForms t' ]
where ts = singleStep t
redSequences :: Term -> [[Term]]
redSequences t
| null ts = [ [t] ]
| otherwise = [ t:rs | t'<-ts, rs<-redSequences t' ]
where ts = singleStep t
-- Particular example:
term0 = Square (Square (Plus (Num 3) (Num 7)))
nfs0 = normalForms term0
rsq0 = redSequences term0
-- Using Gofer:
--
-- ? length nfs0
-- 547
-- (188076 reductions, 340335 cells, 4 garbage collections)
-- ?
--