OSR/WOPT | OSR/ROFF | |
f1 | 93.42% | 93.51% |
f2 | 94.08% | 95.84% |
f3 | 63.27% | 65% |
f4 | 69.66% | 69.14% |
f5 | 97% | 97.1% |
f6 | 8.66% | 8.69% |
f7 | 13.71% | 13.72% |
OSR = Optimizations with shortcut rules: ghc -fglasgow-exts -O fi.hs
WOPT = Without optimizations: ghc --make -fglasgow-exts fi.hs
ROFF = Without optimizations, all rules off: ghc -fglasgow-exts -frules-off fi.hs
![]() |
module MonShortcut where mmap :: Monad m => ( a -> b) -> (m a -> m b) mmap f m = do {a <- m; return (f a)} {-# NOINLINE mmap #-} {-# RULES "bind->mmap" forall m f. m >>= (\a -> return (f a)) = mmap f m #-} ------- mbuild for lists mbuild :: Monad m => (forall b. (a -> b -> b) -> b -> m b) -> m [a] mbuild g = g (:) [] {-# INLINE [1] mbuild #-} {-# RULES "foldr/mbuild" forall c n (g :: forall b. (a -> b -> b) -> b -> m b). mmap (foldr c n)(mbuild g) = g c n #-} ------- mbuild for arithmetic expresions data Exp = Num Int | Add Exp Exp deriving Show foldE :: (Int -> a) -> (a -> a -> a) -> Exp -> a foldE num add = fE where fE (Num n) = num n fE (Add e e') = add (fE e) (fE e') mbuildE :: Monad m => (forall a. (Int -> a) -> (a -> a -> a) -> m a) -> m Exp mbuildE g = g Num Add {-# INLINE [1] mbuildE #-} {-# RULES "foldE/mbuildE" forall num add (g :: forall a. (Int -> a) -> (a -> a -> a) -> m a). mmap (foldE num add) (mbuildE g) = g num add #-} |
module Main where import IO import MonShortcut import Control.Monad ------- zipWithM in terms of mbuild {-# RULES "zipWithM->mbuild" forall f xs ys. zipWithM f xs ys = mbuild (gzipWM f xs ys) #-} gzipWM f (x:xs) (y:ys) c n = do z <- f x y zs <- gzipWM f xs ys c n return (c z zs) gzipWM f _ _ c n = return n ------- length' in terms of foldr {-# RULES "length'->foldr" length' = foldr (\x n -> n+1) 0 #-} length' [] = 0 length' (x:xs) = 1 + length' xs ------- Auxiliary definitions xs = enumFromTo 1 1000000 put x = do {putStr (show x); return x} ------- Test f :: IO Int f = do as <- zipWithM (\x y -> put (x+y)) xs xs return (length' as) main = f >> return () |
module Main where import IO import MonShortcut import Control.Monad ------- mapM in terms of mbuild {-# RULES "mapM->mbuild" forall f xs. mapM f xs = mbuild (gmapM f xs) #-} gmapM f [] c n = return n gmapM f (x:xs) c n = do y <- f x ys <- gmapM f xs c n return (c y ys) ------- sum' in terms of foldr {-# RULES "sum'->foldr" sum' = foldr (+) 0 #-} sum' [] = 0 sum' (x:xs) = x + sum' xs ------- Auxiliary definitions xs = enumFromTo 1 1000000 put x = do {putStr (show x); return x} ------- Examples f :: IO Int f = do as <- mapM (\x -> put (x*x)) xs return (sum' as) main = f >> return () |
module Main where import IO import MonShortcut import Control.Monad ------- hGetContents in terms of mbuild {-# RULES "hGetContents->mbuild" forall h. hGetContents h = mbuild (hGetC h) #-} hGetC h c n = do eof <- hIsEOF h if eof then do hClose h return n else do x <- hGetChar h xs <- hGetC h c n return (c x xs) ------- filter in terms of foldr {-# RULES "filter->foldr" forall p. filter p = foldr (\x xs-> if p x then (x:xs) else xs) [] #-} ------- Test f = \h -> do cs <- hGetContents h return (filter (/='\n') cs) {-# NOINLINE f #-} main = do h <- openFile "sblp08.tex" ReadMode zs <- f h putStr zs |
module Main where import IO import MonShortcut import Control.Monad ------- hGetContents in terms of mbuild {-# RULES "hGetContents->mbuild" forall h. hGetContents h = mbuild (hGetC h) #-} hGetC h c n = do eof <- hIsEOF h if eof then do hClose h return n else do x <- hGetChar h xs <- hGetC h c n return (c x xs) ------- length' in terms of foldr {-# RULES "length'->foldr" length' = foldr (\x n -> n+1) 0 #-} length' [] = 0 length' (x:xs) = 1 + length' xs ------- Test f = \h -> do cs <- hGetContents h return (length' cs) {-# NOINLINE f #-} main = do h <- openFile "sblp08.tex" ReadMode f h |
module Main where import IO import MonShortcut import Control.Monad ------- mapM in terms of mbuild {-# RULES "mapM->mbuild" forall f xs. mapM f xs = mbuild (gmapM f xs) #-} gmapM f [] c n = return n gmapM f (x:xs) c n = do y <- f x ys <- gmapM f xs c n return (c y ys) ------- filter in terms of foldr {-# RULES "filter->foldr" forall p. filter p = foldr (\x xs-> if p x then (x:xs) else xs) [] #-} ------- Auxiliary definitions xs = enumFromTo 1 1000000 put x = do {putStr (show x); return x} ------- Test f :: IO [Int] f = do ns <- mapM (\x -> put (x*x)) xs return (filter even ns) main = f >> return () |
module Main where import IO import MonShortcut import Control.Monad import GHC.Base ------- Parser Monad newtype Parser a = P (String -> [(a,String)]) instance Monad Parser where return a = P (\cs -> [(a,cs)]) p >>= f = P (\cs -> concat [parse (f a) cs' | (a,cs') <- parse p cs]) parse :: Parser a -> String -> [(a,String)] parse (P p) = p pzero :: Parser a pzero = P (\cs -> []) (<|>) :: Parser a -> Parser a -> Parser a (P p) <|> (P q) = P (\cs -> case p cs ++ q cs of [] -> [] (x:xs) -> [x]) item :: Parser Char item = P (\cs -> case cs of "" -> [] (c:cs) -> [(c,cs)]) ------- parsing digits digit :: Parser Int digit = do c <- item if isDigit c then return (ord c - ord '0') else pzero isDigit c = (c >= '0') && (c <= '9') digits :: Parser [Int] digits = do {d <- digit; ds <- digits; return (d:ds)} <|> return [] ------- parser for arithmetic expressions {- parsing -} expression :: Parser Exp {- INLINE [0] expression -} expression = do n <- number plusop e <- expression return (Add (Num n) e) <|> do n <- number return (Num n) number :: Parser Int number = do (n,p) <- numpow10 return n numpow10 = do {d <- digit; (n,p) <- numpow10; return (d*p+n,10*p)} <|> return (0,1) plusop = do {c <- item; if c == '+' then return () else pzero} {- evaluation -} eval :: Exp -> Int eval (Num n) = n eval (Add e e') = eval e + eval e' {-# INLINE [1] eval #-} {- parsing & evalauation -} --evalexp :: Parser Int evalexp = do e <- expression return (eval e) {-# NOINLINE evalexp #-} {-# RULES "eval->foldE" eval = foldE id (+) "expression->mbuildE" expression = mbuildE gexp #-} gexp num add = do n <- number plusop e <- gexp num add return (add (num n) e) <|> do n <- number return (num n) ------- Auxiliary definitions s23 = "+2+3" ++ s23 expr = '1' : take 1000000 s23 put x = do {putStr (show x); return x} ------- Test main = print $ fst $ head $ parse evalexp expr |
module Main where import IO import MonShortcut import Control.Monad import GHC.Base ------- Parser Monad newtype Parser a = P (String -> [(a,String)]) instance Monad Parser where return a = P (\cs -> [(a,cs)]) p >>= f = P (\cs -> concat [parse (f a) cs' | (a,cs') <- parse p cs]) parse :: Parser a -> String -> [(a,String)] parse (P p) = p pzero :: Parser a pzero = P (\cs -> []) (<|>) :: Parser a -> Parser a -> Parser a (P p) <|> (P q) = P (\cs -> case p cs ++ q cs of [] -> [] (x:xs) -> [x]) item :: Parser Char item = P (\cs -> case cs of "" -> [] (c:cs) -> [(c,cs)]) ------- parsing digits digit :: Parser Int digit = do c <- item if isDigit c then return (ord c - ord '0') else pzero isDigit c = (c >= '0') && (c <= '9') digits :: Parser [Int] {- INLINE [0] digits -} digits = do {d <- digit; ds <- digits; return (d:ds)} <|> return [] sum' [] = 0 sum' (x:xs) = x + sum' xs {-# RULES "sum'->foldr" sum' = foldr (+) 0 "digits->mbuild" digits = mbuild gdig #-} gdig c n = do {d <- digit; ds <- gdig c n; return (c d ds)} <|> return n ------- divisible by 3 --sumDigits :: Parser Int sumDigits = do {ds <- digits; return (sum' ds)} {-# NOINLINE sumDigits #-} divby3 :: Parser Bool divby3 = do {n <- sumDigits; return (n `mod` 3 == 0)} ------- Auxiliary definitions s123 = "123" ++ s123 number = take 500000 s123 put x = do {putStr (show x); return x} ------- Examples main = print $ fst $ head $ parse divby3 number |