[Pkg-haskell-commits] [SCM] haskell-testpack branch, master, updated. debian/1.0.2-1-4-gb0d6b36
John Goerzen
jgoerzen at complete.org
Fri Apr 23 15:23:17 UTC 2010
The following commit has been merged in the master branch:
commit 1730e96b408aaed4b1b3912b926d61bfd25e28f2
Author: John Goerzen <jgoerzen at complete.org>
Date: Tue Apr 15 21:57:21 2008 -0500
Reworked BinPacking error handling
diff --git a/src/Data/BinPacking.hs b/src/Data/BinPacking.hs
index 6890d2c..8485f92 100644
--- a/src/Data/BinPacking.hs
+++ b/src/Data/BinPacking.hs
@@ -40,18 +40,45 @@ A description of bin packing algorithms can be found at
-}
module Data.BinPacking (BinPacker,
+ BinPackerError(..),
packByOrder,
packLargeFirst
)
where
import Data.List
+import Control.Monad.Error
-{- | The primary type for bin-packing functions -}
-type BinPacker = (Num size, Ord size, Show obj) =>
+{- | Potential errors returned as Left values by 'BinPacker' functions.
+Calling 'show' on this value will produce a nice error message suitable for
+display. -}
+data (Num size, Ord size, Show size, Show obj) => BinPackerError size obj =
+ BPTooFewBins [(size, obj)] -- ^ Ran out of bins; attached value is the list of objects that don't fit
+ | BPSizeTooLarge size (size, obj) -- ^ Bin size1 exceeded by at least the given object and size
+ | BPOther String -- ^ Other error
+ deriving (Eq, Read)
+
+instance (Num size, Ord size, Show size, Show obj) => Show (BinPackerError size obj) where
+ show (BPTooFewBins _) = "Too few bins"
+ show (BPSizeTooLarge binsize (objsize, obj)) =
+ "Size " ++ show objsize ++ " greater than bin size " ++ show binsize
+ ++ " at " ++ show obj
+ show (BPOther x) = x
+
+{- | Let us use this as part of the Either monad -}
+instance (Num size, Ord size, Show size, Show obj) => Error (BinPackerError size obj) where
+ strMsg = BPOther
+
+{- | The primary type for bin-packing functions.
+
+These functions take a list of size of bins. If every bin is the same size,
+you can pass @(repeat binSize)@ to pass an infinite list of bins if the
+same size. Any surplus bins will simply be ignored. -}
+type BinPacker = (Num size, Ord size, Show size, Show obj) =>
[size] -- ^ The sizes of bins
-> [(size, obj)] -- ^ The sizes and objects
- -> Either String [[(size, obj)]] -- ^ Either error or results
+ -> Either (BinPackerError size obj) [[(size, obj)]] -- ^ Either error or results
+
{- | Pack objects into bins, preserving order. Objects will be taken from the
input list one by one, and added to each bin until the bin is full. Work will
@@ -60,11 +87,11 @@ bins. This is the simplest and most naive bin-packing algorithm, but
may not make very good use of bin space. -}
packByOrder :: BinPacker
packByOrder _ [] = Right [] -- Ran out of sizes
-packByOrder [] _ = Left "Ran out of bins"
+packByOrder [] remainder = Left (BPTooFewBins remainder)
packByOrder (thisbinsize:otherbins) sizes =
let fillBin _ [] = Right []
fillBin accumsize ((s, o):xs)
- | s > thisbinsize = Left $ "Size " ++ show s ++ " greater than bin size " ++ show thisbinsize ++ " at " ++ show o
+ | s > thisbinsize = Left $ BPSizeTooLarge thisbinsize (s, o)
| s + accumsize > thisbinsize = Right []
| otherwise = do next <- fillBin (accumsize + s) xs
return $ (s, o) : next
@@ -82,14 +109,14 @@ packLargeFirst bins sizes = packLargeFirst' bins (sortBy fstSort sizes)
packLargeFirst' :: BinPacker
packLargeFirst' _ [] = Right [] -- Ran out of sizes
-packLargeFirst' [] _ = Left "Ran out of bins"
+packLargeFirst' [] remainder = Left (BPTooFewBins remainder)
packLargeFirst' (thisbinsize:otherbins) sizes =
let fillBin _ [] = Right []
fillBin accumsize sizelist =
case break (\x -> (fst x) + accumsize < thisbinsize) sizelist of
(_, []) ->
if accumsize == 0
- then Left $ "No items small enough to fit in bin " ++ show thisbinsize ++ "; remainder is " ++ show sizelist
+ then Left $ BPSizeTooLarge thisbinsize (head sizelist)
else Right []
(nonmatches, ((s, o):matchxs)) ->
do next <- fillBin (accumsize + s) (nonmatches ++ matchxs)
--
haskell-testpack
More information about the Pkg-haskell-commits
mailing list