Holumbus-Searchengine-1.2.0: src/Control/Sequential/MapFoldBinary.hs
{-# OPTIONS #-}
-- ------------------------------------------------------------
{- |
Module : Control.Sequential.MapFoldBinary
Copyright : Copyright (C) 2010 Uwe Schmidt
License : MIT
Maintainer : Uwe Schmidt (uwe@fh-wedel.de)
Stability : experimental
A map-fold function for interleaved map and fold.
The elements of a list are processed like in a binary tree.
-}
-- ------------------------------------------------------------
module Control.Sequential.MapFoldBinary
( mapFoldBinary
, mapFoldBinaryM
)
where
-- ------------------------------------------------------------
-- | Pure version of binary map fold
--
-- @mapFoldBinary id (+) [1..8]@ adds the elements of a list in the following order:
-- @(((1+2)+(3+4))+((5+6)+(7+8)))@
mapFoldBinary :: (a -> b) -> (b -> b -> b) -> [a] -> b
mapFoldBinary m f xs0 = fst $ mapLeft (1::Int) $ map1 xs0
where
-- map1 :: [a] -> (b, [a])
map1 (x:xs) = (m x, xs)
map1 [] = error "mapFoldBinary with empty list"
-- mapLeft :: Int -> (b, [a]) -> (b, [a])
mapLeft n (r1, xs1)
| null xs1 = (r1, [])
| null xs2 = (r, [])
| otherwise = mapLeft (n + 1) (r, xs2)
where
(r2, xs2) = mapRight n xs1
r = f r1 r2
-- mapRight :: Int -> [a] -> (b, [a])
mapRight 1 xs = map1 xs
mapRight n xs
| null xs1 = (r1, [] )
| otherwise = (f r1 r2, xs2)
where
(r1, xs1) = mapRight (n - 1) xs
(r2, xs2) = mapRight (n - 1) xs1
-- ------------------------------------------------------------
{-
t1 :: [Int] -> String
t1 = mapFoldBinary show (\ x y -> "(" ++ x ++ "+" ++ y ++ ")")
r1 :: String
r1 = t1 [1..8]
-}
-- ------------------------------------------------------------
-- | Monadic version of a binary map fold
--
-- The elements of a list are mapped and folded in the same way as in the pure version.
-- The map and fold operations are interleaved. In the above example the expressions are evaluated
-- from left to right, folding is performed, as early as possible.
mapFoldBinaryM :: (Monad m) =>
(a -> m b) -> (b -> b -> m b) -> [a] -> m b
mapFoldBinaryM m f xs0 = do
r0 <- map1 xs0
rn <- mapLeft (1::Int) r0
return (fst rn)
where
-- map1 :: [a] -> m (b, [a])
map1 (x:xs) = do
r1 <- m x
return (r1, xs)
map1 [] = error "mapFoldBinary with empty list"
-- mapLeft :: Int -> (b, [a]) -> m (b, [a])
mapLeft n r@(r1, xs1)
| null xs1 = return r
| otherwise = do
(r2, xs2) <- mapRight n xs1
res <- f r1 r2
( if null xs2
then return
else mapLeft (n + 1) ) (res, xs2)
-- mapRight :: Int -> [a] -> m (b, [a])
mapRight 1 xs = map1 xs
mapRight n xs = do
r@(r1, xs1) <- mapRight (n - 1) xs
if null xs1
then return r
else do
(r2, xs2) <- mapRight (n - 1) xs1
res <- f r1 r2
return (res, xs2)
-- ------------------------------------------------------------
{-
t1m :: [Int] -> IO String
t1m = mapFoldBinaryM
( \ x -> ( do
print x
return (show x)
)
)
( \ x y -> ( do
putStrLn $ "(" ++ x ++ "+" ++ y ++ ")"
return $ "(" ++ x ++ "+" ++ y ++ ")"
)
)
r1m :: IO String
r1m = t1m [1..8]
-}
-- ------------------------------------------------------------