packages feed

toolshed 0.14.0.0 → 0.15.0.0

raw patch · 17 files changed

+411/−73 lines, 17 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- ToolShed.Test.SelfValidate: instance Arbitrary Primes
- ToolShed.Test.SelfValidate: instance Eq Primes
- ToolShed.Test.SelfValidate: instance Ord Primes
- ToolShed.Test.SelfValidate: instance SelfValidator Primes
- ToolShed.Test.SelfValidate: instance Show Primes
- ToolShed.Test.SelfValidate: quickChecks :: IO ()
+ ToolShed.Data.List: permutationsBy :: Matches a -> [[a]] -> [[a]]
+ ToolShed.Data.List: type Matches a = a -> a -> Bool
+ ToolShed.Data.Quadruple: curry4 :: ((a, b, c, d) -> result) -> a -> b -> c -> d -> result
+ ToolShed.Data.Quadruple: getFirst :: (a, b, c, d) -> a
+ ToolShed.Data.Quadruple: getFourth :: (a, b, c, d) -> d
+ ToolShed.Data.Quadruple: getSecond :: (a, b, c, d) -> b
+ ToolShed.Data.Quadruple: getThird :: (a, b, c, d) -> c
+ ToolShed.Data.Quadruple: uncurry4 :: (a -> b -> c -> d -> result) -> (a, b, c, d) -> result
+ ToolShed.Data.Triple: curry3 :: ((a, b, c) -> result) -> a -> b -> c -> result
+ ToolShed.Data.Triple: getFirst :: (a, b, c) -> a
+ ToolShed.Data.Triple: getSecond :: (a, b, c) -> b
+ ToolShed.Data.Triple: getThird :: (a, b, c) -> c
+ ToolShed.Data.Triple: uncurry3 :: (a -> b -> c -> result) -> (a, b, c) -> result
+ ToolShed.Defaultable: instance (Defaultable a, Defaultable b, Defaultable c) => Defaultable (a, b, c)
- ToolShed.Data.List: equalityBy :: Eq b => (a -> b) -> a -> a -> Bool
+ ToolShed.Data.List: equalityBy :: Eq b => (a -> b) -> Matches a
- ToolShed.Data.List: findConvergenceBy :: (a -> a -> Bool) -> [a] -> a
+ ToolShed.Data.List: findConvergenceBy :: Matches a -> [a] -> a

Files

changelog view
@@ -26,8 +26,7 @@ 	* Added functions 'merge' & 'mergeBy' to module "ToolShed.ListPlus" & exported a new type-synonym 'ToolShed.ListPlus.ChunkLength'. 	* Uploaded to <http://hackage.haskell.org/packages/hackage.html>. 0.12.0.0-	* Added module "ToolShed.TimeAction" to measure the CPU-seconds required for an IO-action.-	* Added module "Pair".+	* Added modules "ToolShed.TimeAction" to measure the CPU-seconds required for an IO-action, & "Pair". 0.12.0.1 	* Removed unnecessary type-context 'Ord' from 'ToolShed.ListPus.mergeBy' & reimplemented 'ToolShed.ListPus.merge' in terms of 'ToolShed.ListPus.mergeBy'. 	* Added 'ToolShed.ListPlus.runLengthEncode' & 'ToolShed.ListPlus.runLengthDecode'.@@ -44,8 +43,7 @@ 	* Added instances of 'ToolShed.SelfValidate.SelfValidator' for 'Data.Maybe.Maybe' '(,)', 'Data.Set.Set', 'Data.Map.Map' & 'Data.Array.IArray.Array'. 	* Added instance of 'ToolShed.Defaultable.Defaultable' for '(,)'. 	* Added functions 'ToolShed.Data.List.showListWith', 'ToolShed.Data.List.permutations', 'ToolShed.Data.List.gatherBy', 'ToolShed.Data.List.findConvergenceBy', 'ToolShed.Data.List.findConvergence', 'ToolShed.Data.List.gather'.-	* Added module "ToolShed.System.File".-	* Added module "ToolShed.System.Random".+	* Added modules "ToolShed.System.File" & "ToolShed.System.Random". 	* Added method 'ToolShed.SelfValidate.getErrors', & supporting functions 'ToolShed.SelfValidate.getFirstErrors' & 'ToolShed.SelfValidate.extractErrors'. 	* Create module "ToolShed.Arbitrary.*". 	* Added "Main", "ToolShed.Test.QuickChecks" & "ToolShed.Test.Data.List" to facilitate testing.@@ -56,12 +54,22 @@ 	* Defined package's name using program's name, in "Main.hs". 	* Checked package "Base" exports 'Data.Tuple.swap', in "ToolShed.Arbitrary.Array". 	* Relocated "ToolShed.Arbitrary" to "ToolShed.Test.QuickCheck.Arbitrary".-	* Added "ToolShed.Test.ReversibleBoundedEnum", "ToolShed.Test.ReversibleEnum" "ToolShed.Test.ReversibleIO", & "ToolShed.Test.SelfValidate".+	* Added "ToolShed.Test.ReversibleBoundedEnum", "ToolShed.Test.ReversibleEnum", "ToolShed.Test.ReversibleIO", & "ToolShed.Test.SelfValidate". 	* Amended 'ToolShed.System.File.locate' to deal with absolute file-paths. 	* Replaced legacy calls to 'Data.Map.fold' & 'Data.Set.fold', with more expicit calls to 'Data.Map.foldr' & 'Data.Set.foldr' from a more recent version of the "containers" package. 	* Added instance of 'ToolShed.SelfValidate.SelfValidator' for '(,,)'. 	* Trapped null list in 'ToolShed.System.Random.select'.-	* Added "ToolShed.Data.List.nub'".-	* Added 'ToolShed.Data.List.hasDuplicates'.+	* Added functions "ToolShed.Data.List.nub'" & 'ToolShed.Data.List.hasDuplicates'. 	* Migrated functions 'gather', 'gatherBy', 'hasDuplicates' which merely operate on 'Data.Foldable.Foldable' types from module "ToolShed.Data.List", into new module "ToolShed.Data.Foldable".-+0.15.0.0+	* Refactored 'ToolShed.Test.QuickChecks'.+	* Added type 'ToolShed.Data.List.Matches' & function 'ToolShed.Data.List.permutationsBy'.+	* Trapped the case of a null list supplied to 'ToolShed.Data.List.permutationsBy'.+	* Re-implemented 'ToolShed.System.Random.shuffle', using the Fisher-Yates algorithm; which also improved the efficiency.+	* Trapped special cases in 'ToolShed.System.Random.generateSelection'.+	* Added modules "ToolShed.Test.System.Random", "ToolShed.Data.Triple", "ToolShed.Data.Quadruple", "ToolShed.Test.Data.Triple", & "ToolShed.Test.Data.Quadruple".+	* Explicitly closed standard-input in the executable.+	* Replaced calls to 'error' from inside the IO-monad, with 'Control.Monad.fail'.+	* Added an instance for '(,,)', to "ToolShed.Defaultable.Defaultable".+	* Corrected version-string in "Main" used in '--version' option.+	* Corrected the output of 'Main.main.optDescrList.printVersion'.
@@ -2,7 +2,7 @@ 	Dr. Alistair Ward <toolshed at functionalley dot eu>.  Copyright:-	Copyright (C) 2010-2011 Dr. Alistair Ward. All Rights Reserved.+	Copyright (C) 2010-2013 Dr. Alistair Ward. All Rights Reserved.  Home-page: 	http://functionalley.eu
src/Main.hs view
@@ -24,13 +24,7 @@ 	* Facilitates testing. -} -module Main(--- * Types--- ** Type-synonyms---	CommandLineAction,--- * Functions-	main-) where+module Main(main) where  import qualified	Data.List import qualified	Data.Version@@ -52,6 +46,8 @@ -- | Parses the command-line arguments, to determine 'Test.CommandOptions.CommandOptions'. main :: IO () main	= do+	System.IO.hClose System.IO.stdin	--Nothing is read from standard input.+ 	progName	<- System.Environment.getProgName  	let@@ -67,7 +63,7 @@ 			G.Option "q"	["runQuickChecks"]	(G.NoArg $ const runQuickChecks)	"Run Quick-checks using arbitrary data & then exit." 		 ] where 			printVersion, printUsage, runQuickChecks :: IO ()-			printVersion	= System.IO.hPutStrLn System.IO.stderr (Distribution.Text.display packageIdentifier ++ "\n\nCopyright (C) 2011 " ++ author ++ ".\nThis program comes with ABSOLUTELY NO WARRANTY.\nThis is free software, and you are welcome to redistribute it under certain conditions.\n\nWritten by " ++ author ++ ".")	>> System.Exit.exitWith System.Exit.ExitSuccess	where+			printVersion	= System.IO.hPutStrLn System.IO.stderr (Distribution.Text.display packageIdentifier ++ "\n\nCopyright (C) 2010-2013 " ++ author ++ ".\nThis program comes with ABSOLUTELY NO WARRANTY.\nThis is free software, and you are welcome to redistribute it under certain conditions.\n\nWritten by " ++ author ++ ".")	>> System.Exit.exitWith System.Exit.ExitSuccess	where 				packageIdentifier :: Distribution.Package.PackageIdentifier 				packageIdentifier	= Distribution.Package.PackageIdentifier { 					Distribution.Package.pkgName	= Distribution.Package.PackageName progName,	--CAVEAT: coincidentally.
src/ToolShed/Data/Foldable.hs view
@@ -47,3 +47,4 @@ -- | Whether the specified collection contains any equal items. hasDuplicates :: (Data.Foldable.Foldable f, Ord a) => f a -> Bool hasDuplicates	= any ((> 1) . length) . gather+
src/ToolShed/Data/List.hs view
@@ -24,6 +24,7 @@ -- * Types -- ** Type-synonyms 	ChunkLength,+	Matches, -- * Functions 	chunk, 	excise,@@ -36,6 +37,7 @@ 	nub', --	nubWithInt, 	permutations,+	permutationsBy, 	takeUntil, 	showListWith, --	showListWithChar,@@ -43,6 +45,7 @@ ) where  import qualified	Control.Arrow+import			Control.Arrow((&&&)) import qualified	Data.IntSet import qualified	Data.List import qualified	Data.Set@@ -51,17 +54,17 @@ type ChunkLength	= Int  {- |-	* Splits a list into length-@size@ pieces, where @(size >= 0)@.+	* Splits a list into chunks of the specified length. -	* The last chunk will be shorter, if @n@ isn't an aliquot part of the input list-length.+	* The last chunk will be shorter, if the chunk-length isn't an aliquot part of the input list-length. -	* If @(size == 0)@, the resulting list will be an infinite sequence of null lists.+	* If the chunk-length is zero, the resulting list will be an infinite sequence of null lists. -	* CAVEAT: a similar function is available in the module /Data.List.Split/, though this one checks for @(size < 0)@.+	* CAVEAT: a similar function is available in the module /Data.List.Split/, though this one checks for @(chunkLength < 0)@. -} chunk 	:: ChunkLength-	-> [a]		-- ^ The polymorphic input list to be chunked.+	-> [a]	-- ^ The polymorphic input list to be chunked. 	-> [[a]] chunk size list 	| size < 0	= error $ "ToolShed.Data.List.chunk:\tnegative chunk-size=" ++ show size@@ -79,24 +82,60 @@ excise 0	= tail	--Just for efficiency. excise i	= uncurry (++) . Control.Arrow.second tail . splitAt i --- | A convenient way to compose the function-parameter required by 'Data.List.groupBy' or 'Data.List.nubBy'.-equalityBy :: Eq b => (a -> b) -> a -> a -> Bool+-- | The type of function required by 'findConvergenceBy', 'permutationsBy'.+type Matches a	= a -> a -> Bool++-- | A convenient way to compose the 'Matches'-function required by 'findConvergenceBy' & 'permutationsBy'.+equalityBy :: Eq b => (a -> b) -> Matches a equalityBy f x y	= f x == f y --- | Take the first element from the list, which compares equal according to the specified predicate, with the subsequent element.-findConvergenceBy :: (a -> a -> Bool) -> [a] -> a-findConvergenceBy predicate l	= fst . head . dropWhile (not . uncurry predicate) . zip l $ tail l+-- | Take the first element from the (potentially infinite) list, which matches the subsequent element, according to the specified function.+findConvergenceBy :: Matches a -> [a] -> a+findConvergenceBy _ []	=  error "ToolShed.Data.List.findConvergenceBy:\ta null list is too short for convergence to exist"+findConvergenceBy _ [_]	=  error "ToolShed.Data.List.findConvergenceBy:\ta singleton list is too short for convergence to exist"+findConvergenceBy matches l+	| null l'	= error "ToolShed.Data.List.findConvergenceBy:\tno convergence found"+	| otherwise	= fst $ head l'+	where+		l'	= dropWhile (not . uncurry matches) . uncurry zip $ (init &&& tail) l  -- | A specific instance of 'findConvergenceBy'. findConvergence :: Eq a => [a] -> a findConvergence	= findConvergenceBy (==) +{- |+	* The list of all permutations, generated by selecting any one datum from each sub-list in turn, from the specified list of lists.++	* As each item is selected, the remaining lists are filtered according to the specified 'Matches'-function.++	* Thus '/=' could be used to select a different item from each list.+-}+permutationsBy :: Matches a -> [[a]] -> [[a]]+permutationsBy matches lists+	| any null lists	= []	--Required for efficiency, to catch the case [bigList1, bigList2 ... null]+	| otherwise		= slave lists+	where+		slave (xs : xss)	= [x : xs' | x <- xs, xs' <- slave $ map (filter $ matches x) xss]+		slave []		= [[]]++{- |+	* The list of all permutations, generated by selecting any one datum from each sub-list in turn, from the specified list of lists.++	* A specific instance of 'permutationsBy', in which no filtering of subsequent lists is performed after each item is selected.++	* NB: differs from 'Data.List.permutations', which selects items from a single input list.+-}+permutations :: [[a]] -> [[a]]+permutations	= permutationsBy (\_ _ -> True)+ {-# NOINLINE nub' #-} {-# RULES "nub'/Int" nub' = nubWithInt #-}  {- |-	* A version of 'Data.List.nub' with better time-complexity.+	* A strict version of 'Data.List.nub' with better time-complexity. +	* CAVEAT: the specified list must be finite, since the entire set is constructed before streaming to a list.+ 	* CAVEAT: it sorts the output as a side-effect, & consequently it requires a type which implements 'Ord'. -} nub' :: Ord a => [a] -> [a]@@ -129,15 +168,6 @@ -- | A specific instance of 'mergeBy'. merge :: Ord a => [a] -> [a] -> [a] merge	= mergeBy compare--{- |-	* The list of all permutations, generated by selecting any one datum from each sub-list in turn, from the specified list of lists.--	* Taken from <http://www.haskell.org/pipermail/haskell-cafe/2006-June/015975.html>.--}-permutations :: [[a]] -> [[a]]-permutations (xs : xss)	= [ x : xs' | x <- xs, xs' <- permutations xss ]-permutations []		= [[]]  {- | 	* Take until the specified predicate is satisfied; /including/ the item which satisfied it.
src/ToolShed/Data/List/Runlength.hs view
@@ -53,3 +53,4 @@ -- | Performs /run-length/ decoding to retrieve the original unencoded list. decode :: [Code a] -> [a] decode	= concatMap (uncurry replicate)+
+ src/ToolShed/Data/Quadruple.hs view
@@ -0,0 +1,59 @@+{-+	Copyright (C) 2013 Dr. Alistair Ward++	This program is free software: you can redistribute it and/or modify+	it under the terms of the GNU General Public License as published by+	the Free Software Foundation, either version 3 of the License, or+	(at your option) any later version.++	This program is distributed in the hope that it will be useful,+	but WITHOUT ANY WARRANTY; without even the implied warranty of+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+	GNU General Public License for more details.++	You should have received a copy of the GNU General Public License+	along with this program.  If not, see <http://www.gnu.org/licenses/>.+-}+{- |+ [@AUTHOR@]	Dr. Alistair Ward++ [@DESCRIPTION@]	Miscellaneous operations on quadruples.++ [@CAVEAT@]	Import fully qualified, since some identifiers clash with 'ToolShed.Data.Triple'.+-}++module ToolShed.Data.Quadruple(+-- * Functions+	curry4,+	uncurry4,+-- ** Accessors+	getFirst,+	getSecond,+	getThird,+	getFourth+) where++-- | Extends the concept of 'Data.Tuple.curry'.+curry4 :: ((a, b, c, d) -> result) -> a -> b -> c -> d -> result+curry4 f a b c d	= f (a, b, c, d)++-- | Extends the concept of 'Data.Tuple.uncurry'.+uncurry4 :: (a -> b -> c -> d -> result) -> (a, b, c, d) -> result+uncurry4 f (a, b, c, d)	= f a b c d++-- | Access the first datum from the specified quadruple.+getFirst :: (a, b, c, d) -> a+getFirst (a, _, _, _)	= a++-- | Access the second datum from the specified quadruple.+getSecond :: (a, b, c, d) -> b+getSecond (_, b, _, _)	= b++-- | Access the third datum from the specified quadruple.+getThird :: (a, b, c, d) -> c+getThird (_, _, c, _)	= c++-- | Access the fourth datum from the specified quadruple.+getFourth :: (a, b, c, d) -> d+getFourth (_, _, _, d)	= d+
+ src/ToolShed/Data/Triple.hs view
@@ -0,0 +1,54 @@+{-+	Copyright (C) 2013 Dr. Alistair Ward++	This program is free software: you can redistribute it and/or modify+	it under the terms of the GNU General Public License as published by+	the Free Software Foundation, either version 3 of the License, or+	(at your option) any later version.++	This program is distributed in the hope that it will be useful,+	but WITHOUT ANY WARRANTY; without even the implied warranty of+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+	GNU General Public License for more details.++	You should have received a copy of the GNU General Public License+	along with this program.  If not, see <http://www.gnu.org/licenses/>.+-}+{- |+ [@AUTHOR@]	Dr. Alistair Ward++ [@DESCRIPTION@]	Miscellaneous operations on triples.++ [@CAVEAT@]	Import fully qualified, since some identifiers clash with 'ToolShed.Data.Quadruple'.+-}++module ToolShed.Data.Triple(+-- * Functions+	curry3,+	uncurry3,+-- ** Accessors+	getFirst,+	getSecond,+	getThird+) where++-- | Extends the concept of 'Data.Tuple.curry'.+curry3 :: ((a, b, c) -> result) -> a -> b -> c -> result+curry3 f a b c	= f (a, b, c)++-- | Extends the concept of 'Data.Tuple.uncurry'.+uncurry3 :: (a -> b -> c -> result) -> (a, b, c) -> result+uncurry3 f (a, b, c)	= f a b c++-- | Access the first datum from the specified triple.+getFirst :: (a, b, c) -> a+getFirst (a, _, _)	= a++-- | Access the second datum from the specified triple.+getSecond :: (a, b, c) -> b+getSecond (_, b, _)	= b++-- | Access the third datum from the specified triple.+getThird :: (a, b, c) -> c+getThird (_, _, c)	= c+
src/ToolShed/Defaultable.hs view
@@ -31,3 +31,6 @@  instance (Defaultable a, Defaultable b) => Defaultable (a, b)	where 	defaultValue	= (defaultValue, defaultValue)++instance (Defaultable a, Defaultable b, Defaultable c) => Defaultable (a, b, c)	where+	defaultValue	= (defaultValue, defaultValue, defaultValue)
src/ToolShed/System/File.hs view
@@ -103,5 +103,5 @@  	case reads fileContents of 		[(x, _)]	-> return {-to IO-monad-} (filePath, x)	--CAVEAT: discards any unconsumed text.-		_		-> error $ "ToolShed.System.File.fromFile:\tfailed to parse file=" ++ show filePath+		_		-> fail $ "ToolShed.System.File.fromFile:\tfailed to parse file=" ++ show filePath 
src/ToolShed/System/Random.hs view
@@ -31,8 +31,8 @@ ) where  import qualified	Control.Arrow-import qualified	Data.List-import qualified	Data.Ord+import qualified	Data.Sequence+import			Data.Sequence((><), ViewL((:<))) import qualified	System.Random  -- | Constructs an infinite list of independent random-generators.@@ -40,37 +40,41 @@ randomGens	= uncurry (:) . Control.Arrow.second randomGens {-recurse-} . System.Random.split  {- |-	* Shuffles the specified finite list.+	* Shuffles the specified finite list, using the /Fisher-Yates/ algorithm; <http://en.wikipedia.org/wiki/Fisher-Yates_shuffle>.  	* The resulting list has the same length and constituents as the original; only the order has changed. -	* CAVEAT: the implementation /zips/ a list of integers, with the specified polymorphic list, then sorts it,-	but when identical random integers are generated, the sort-algorithm being /stable/ always return the corresponding items in their original order.-	The shuffle is therefore imperfect,-	but on a /64-bit/ machine, it would need such a large list of items, for the probability of randomly generating two identical integers, to be significant,-	that /sort/ probably wouldn't return in a reasonable time anyway.-	Ideally, it would be amended to use an /unstable/ sort-algorithm.+	* The input list is traversed, but the items aren't evaluated. -} shuffle :: System.Random.RandomGen randomGen => randomGen -> [a] -> [a]-shuffle randomGen	= map snd . Data.List.sortBy (Data.Ord.comparing fst) . zip (System.Random.randoms randomGen :: [Int])+shuffle _ []		= []		--Not strictly necessary.+shuffle _ singleton@[_]	= singleton	--Not strictly necessary.+shuffle randomGen l	= slave randomGen s (pred $ Data.Sequence.length s)	where+	s	= Data.Sequence.fromList l +	slave randomGen' s' maxIndex+		| maxIndex < 0	= []+		| otherwise	= selection : slave randomGen'' (first >< remainder) (pred maxIndex) {-recurse-}+		where+			(randomIndex, randomGen'')	= System.Random.randomR (0, maxIndex) randomGen'+			(first, selection :< remainder)	= Control.Arrow.second Data.Sequence.viewl $ Data.Sequence.splitAt randomIndex s'+ {- |-	* Generate an infinite list of items, each randomly selected from the specified finite list.+	* Generate an infinite list of items, each independently randomly selected from the specified finite list.  	* CAVEAT: because the selections are made non-destructively, duplicates may be returned; cf. 'shuffle'. -} generateSelection :: System.Random.RandomGen randomGen => randomGen -> [a] -> [a]+generateSelection _ []		= error "ToolShed.System.Random.generateSelection:\tnull list"+generateSelection _ [x]		= repeat x	--Not strictly necessary, but more efficient. generateSelection randomGen l	= map (l !!) $ System.Random.randomRs (0, pred $ length l) randomGen --- | Return a random element from the specified list.+-- | Return a randomly selected element from the specified list. select :: System.Random.RandomGen randomGen => randomGen -> [a] -> a-select _ []		= error "ToolShed.System.Random.generateSelection:\tnull list"-select randomGen l	= head $ generateSelection randomGen l+select randomGen	= head . generateSelection randomGen  {- |-	* Generate an infinite list of items, each randomly selected, from the specified finite list of /bounded/ items.--	* Because the selections are made non-destructively, duplicates may be returned.+	* Generate an infinite list of data, each independently selected random instances of the specified /bounded/ type.  	* E.g. @ (generateSelectionFromBounded `fmap` System.Random.getStdGen) :: IO [Bool] @. -}
src/ToolShed/Test/Data/List.hs view
@@ -36,9 +36,9 @@ quickChecks :: IO () quickChecks = 	Test.QuickCheck.quickCheck prop_chunk-	>> Test.QuickCheck.quickCheck prop_findConvergence+	>> Test.QuickCheck.quickCheck `mapM` [prop_findConvergence, prop_permutationsBy'] 	>> Test.QuickCheck.quickCheck prop_nub-	>> Test.QuickCheck.quickCheck prop_permutations+	>> Test.QuickCheck.quickCheck `mapM` [prop_permutations, prop_permutations', prop_permutationsBy] 	>> Test.QuickCheck.quickCheck prop_linearise 	>> Test.QuickCheck.quickCheck prop_merge 	where@@ -51,9 +51,21 @@ 		prop_nub :: [Int] -> Test.QuickCheck.Property 		prop_nub x	= Test.QuickCheck.label "prop_nub" $ ToolShed.Data.List.nub' x == Data.List.sort (Data.List.nub x) -		prop_permutations :: [[Int]] -> Test.QuickCheck.Property+		prop_permutations, prop_permutations', prop_permutationsBy :: [[Int]] -> Test.QuickCheck.Property 		prop_permutations l	= not (null l')	==> Test.QuickCheck.label "prop_permutations" $ length (ToolShed.Data.List.permutations l') == product (map length l')	where 			l'	= take 6 $ map (take 6) l	--Limit the task.++		prop_permutations' l	= not (null l') && all (not . null) l'	==> Test.QuickCheck.label "prop_permutations'" . (== 1) . length . Data.List.nub . map length $ ToolShed.Data.List.permutations l'	where+			l'	= take 7 $ map (take 5) l	--Limit the task.++		prop_permutationsBy l	= and [not $ null l', all (not . null) l', not $ null permutations]	==> Test.QuickCheck.label "prop_permutationsBy" . (== 1) . length . Data.List.nub $ map (length . Data.List.nub) permutations	where+			l'		= take 8 $ map (take 4) l	--Limit the task.+			permutations	= ToolShed.Data.List.permutationsBy (/=) l'++		prop_permutationsBy' :: Int -> Test.QuickCheck.Property+		prop_permutationsBy' i	= Test.QuickCheck.label "prop_permutationsBy'" . all ((== range) . Data.List.sort) . ToolShed.Data.List.permutationsBy (/=) $ replicate (succ i') range	where+			i'	= succ $ mod i 7+			range	= [0 .. i']  		prop_linearise :: [(Int, Int)] -> Test.QuickCheck.Property 		prop_linearise l	= Test.QuickCheck.label "prop_linearise" $ map (\[x, y] -> (x, y)) (ToolShed.Data.List.chunk 2 $ ToolShed.Data.List.linearise l) == l
+ src/ToolShed/Test/Data/Quadruple.hs view
@@ -0,0 +1,36 @@+{-+	Copyright (C) 2013 Dr. Alistair Ward++	This program is free software: you can redistribute it and/or modify+	it under the terms of the GNU General Public License as published by+	the Free Software Foundation, either version 3 of the License, or+	(at your option) any later version.++	This program is distributed in the hope that it will be useful,+	but WITHOUT ANY WARRANTY; without even the implied warranty of+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+	GNU General Public License for more details.++	You should have received a copy of the GNU General Public License+	along with this program.  If not, see <http://www.gnu.org/licenses/>.+-}+{- |+ [@AUTHOR@]	Dr. Alistair Ward++ [@DESCRIPTION@]	Defines /QuickCheck/-properties "ToolShed.Data.Quadruple".+-}++module ToolShed.Test.Data.Quadruple(+-- * Functions+	quickChecks+) where++import qualified	Test.QuickCheck+import qualified	ToolShed.Data.Quadruple++-- | Defines invariant properties.+quickChecks :: IO ()+quickChecks = Test.QuickCheck.quickCheck prop_accessors	where+	prop_accessors :: (Int, Char, Bool, Float) -> Test.QuickCheck.Property+	prop_accessors quadruple	= Test.QuickCheck.label "prop_accessors" $ (f ToolShed.Data.Quadruple.getFirst quadruple, f ToolShed.Data.Quadruple.getSecond quadruple, f ToolShed.Data.Quadruple.getThird quadruple, ToolShed.Data.Quadruple.getFourth quadruple) == quadruple	where+		f	= ToolShed.Data.Quadruple.uncurry4 . ToolShed.Data.Quadruple.curry4
+ src/ToolShed/Test/Data/Triple.hs view
@@ -0,0 +1,37 @@+{-+	Copyright (C) 2013 Dr. Alistair Ward++	This program is free software: you can redistribute it and/or modify+	it under the terms of the GNU General Public License as published by+	the Free Software Foundation, either version 3 of the License, or+	(at your option) any later version.++	This program is distributed in the hope that it will be useful,+	but WITHOUT ANY WARRANTY; without even the implied warranty of+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+	GNU General Public License for more details.++	You should have received a copy of the GNU General Public License+	along with this program.  If not, see <http://www.gnu.org/licenses/>.+-}+{- |+ [@AUTHOR@]	Dr. Alistair Ward++ [@DESCRIPTION@]	Defines /QuickCheck/-properties "ToolShed.Data.Triple".+-}++module ToolShed.Test.Data.Triple(+-- * Functions+	quickChecks+) where++import qualified	Test.QuickCheck+import qualified	ToolShed.Data.Triple++-- | Defines invariant properties.+quickChecks :: IO ()+quickChecks = Test.QuickCheck.quickCheck prop_accessors	where+	prop_accessors :: (Int, Char, Bool) -> Test.QuickCheck.Property+	prop_accessors triple	= Test.QuickCheck.label "prop_accessors" $ (f ToolShed.Data.Triple.getFirst triple, f ToolShed.Data.Triple.getSecond triple, f ToolShed.Data.Triple.getThird triple) == triple	where+		f	= ToolShed.Data.Triple.uncurry3 . ToolShed.Data.Triple.curry3+
src/ToolShed/Test/QuickChecks.hs view
@@ -25,17 +25,27 @@ 	run ) where +import qualified	Control.Arrow import qualified	ToolShed.Test.Data.Foldable import qualified	ToolShed.Test.Data.List import qualified	ToolShed.Test.Data.List.Runlength-import qualified	ToolShed.Test.SelfValidate import qualified	ToolShed.Test.Data.List.Splits+import qualified	ToolShed.Test.Data.Quadruple+import qualified	ToolShed.Test.Data.Triple+import qualified	ToolShed.Test.SelfValidate+import qualified	ToolShed.Test.System.Random  -- | Run the /quickChecks/-functions for modules supporting this feature. run :: IO ()-run	= putStrLn "Data.Foldable"		>> ToolShed.Test.Data.Foldable.quickChecks-	>> putStrLn "Data.List"			>> ToolShed.Test.Data.List.quickChecks-	>> putStrLn "Data.List.Runlength"	>> ToolShed.Test.Data.List.Runlength.quickChecks-	>> putStrLn "Data.List.Splits"		>> ToolShed.Test.Data.List.Splits.quickChecks-	>> putStrLn "SelfValidate"		>> ToolShed.Test.SelfValidate.quickChecks-+run	= mapM_ (+	uncurry (>>) . Control.Arrow.first putStrLn+ ) [+	("Data.Foldable",	ToolShed.Test.Data.Foldable.quickChecks),+	("Data.List",		ToolShed.Test.Data.List.quickChecks),+	("Data.List.Runlength",	ToolShed.Test.Data.List.Runlength.quickChecks),+	("Data.List.Splits",	ToolShed.Test.Data.List.Splits.quickChecks),+	("Data.Quadruple",	ToolShed.Test.Data.Quadruple.quickChecks),+	("Data.Triple",		ToolShed.Test.Data.Triple.quickChecks),+	("SelfValidate",	ToolShed.Test.SelfValidate.quickChecks),+	("System.Random",	ToolShed.Test.System.Random.quickChecks)+ ]
+ src/ToolShed/Test/System/Random.hs view
@@ -0,0 +1,82 @@+{-+	Copyright (C) 2013 Dr. Alistair Ward++	This program is free software: you can redistribute it and/or modify+	it under the terms of the GNU General Public License as published by+	the Free Software Foundation, either version 3 of the License, or+	(at your option) any later version.++	This program is distributed in the hope that it will be useful,+	but WITHOUT ANY WARRANTY; without even the implied warranty of+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+	GNU General Public License for more details.++	You should have received a copy of the GNU General Public License+	along with this program.  If not, see <http://www.gnu.org/licenses/>.+-}+{- |+ [@AUTHOR@]	Dr. Alistair Ward++ [@DESCRIPTION@]	Defines /QuickCheck/-properties "ToolShed.System.Random".+-}++module ToolShed.Test.System.Random(+-- * Functions+--	getMean,+--	getStandardDeviation+	quickChecks+) where++import qualified	Control.Arrow+import			Control.Arrow((&&&),(***))+import qualified	Data.Foldable+import qualified	Data.List+import qualified	Data.Map+import qualified	System.Random+import qualified	Test.QuickCheck+import qualified	ToolShed.System.Random++-- | Determines the /mean/ of the specified numbers+getMean :: (Data.Foldable.Foldable f, Real r, Fractional result) => f r -> result+getMean	= uncurry (/) . (realToFrac *** fromIntegral) . Data.Foldable.foldr (\i -> (+ i) *** succ) (0, 0 :: Int)++-- | Find the standard-deviation of the specified list.+getStandardDeviation :: (Data.Foldable.Foldable f, Functor f, Real r) => f r -> Double+getStandardDeviation x	= sqrt . getMean $ fmap ((^ (2 :: Int)) . (+ negate (getMean x :: Rational)) . toRational) x++-- | Defines invariant properties.+quickChecks :: IO ()+quickChecks+	= Test.QuickCheck.quickCheck prop_shuffle+	>> Test.QuickCheck.quickCheck prop_shuffleDistribution+	where+		prop_shuffle :: Int -> Int -> Test.QuickCheck.Property+		prop_shuffle seed l	= Test.QuickCheck.label "prop_shuffle" . (== testList) . Data.List.sort $ ToolShed.System.Random.shuffle (System.Random.mkStdGen seed) testList	where+			testList	= [0 .. l `mod` 10000]++		prop_shuffleDistribution :: Int -> Test.QuickCheck.Property+		prop_shuffleDistribution	= Test.QuickCheck.label "prop_shuffleDistribution" . all (+			uncurry (&&) . (+				(+					< recip 20 {-empirically-}	--The ideal value for a uniform distribution, would be zero.+				) . (+					/ getStandardDeviation (populationSize : replicate (pred $ length testList) 0)	--Normalise wrt the worst-case; which occurs when this column contains the same letter, for each test-case in the population.+				) . getStandardDeviation &&& (+					== populationSize	--Confirm the size of the test-data.+				) . Data.Foldable.sum+			)+		 ) . map (+			foldr (+				uncurry $ Data.Map.insertWith (+)+			) (+				Data.Map.fromList . zip testList $ repeat (0 :: Int)	--Initial value.+			) . (`zip` repeat 1)	--Count the instances of each letter in this column, which for a uniform distribution, should be approximately the same.+		 ) . Data.List.transpose {-examine the columns-} . take populationSize . map fst {-shuffled digits-} . tail {-drop initial value-} . iterate (+			Control.Arrow.first (`ToolShed.System.Random.shuffle` testList) . System.Random.split . snd+		 ) . (,) undefined . System.Random.mkStdGen	where+			testList :: String+			testList	= ['a' .. 'z']++			populationSize :: Int+			populationSize	= 1000+
toolshed.cabal view
@@ -1,8 +1,8 @@ --Package-properties Name:			toolshed-Version:		0.14.0.0+Version:		0.15.0.0 Cabal-Version:		>= 1.6-Copyright:		(C) 2010 Dr. Alistair Ward+Copyright:		(C) 2010-2013 Dr. Alistair Ward License:		GPL License-file:		LICENSE Author:			Dr. Alistair Ward@@ -11,7 +11,7 @@ Build-Type:		Simple Description:		An ill-defined collection of simple unrelated utilities used by other packages from <http://functionalley.eu> Category:		Utils-Tested-With:		GHC == 6.10, GHC == 6.12, GHC == 7.0, GHC == 7.4+Tested-With:		GHC == 7.4 Homepage:		http://functionalley.eu Maintainer:		toolshed <at> functionalley <dot> eu Bug-reports:		toolshed <at> functionalley <dot> eu@@ -35,6 +35,8 @@         ToolShed.Data.List.Runlength         ToolShed.Data.List.Splits         ToolShed.Data.Pair+        ToolShed.Data.Quadruple+        ToolShed.Data.Triple         ToolShed.Defaultable         ToolShed.Options         ToolShed.SelfValidate@@ -42,14 +44,13 @@         ToolShed.System.Random         ToolShed.System.TimeAction         ToolShed.System.TimePure-        ToolShed.Test.ReversibleBoundedEnum-        ToolShed.Test.ReversibleEnum-        ToolShed.Test.ReversibleIO-        ToolShed.Test.SelfValidate         ToolShed.Test.QuickCheck.Arbitrary.Array         ToolShed.Test.QuickCheck.Arbitrary.ArrayElem         ToolShed.Test.QuickCheck.Arbitrary.Map         ToolShed.Test.QuickCheck.Arbitrary.Set+        ToolShed.Test.ReversibleBoundedEnum+        ToolShed.Test.ReversibleEnum+        ToolShed.Test.ReversibleIO      Build-depends:         array,@@ -80,11 +81,15 @@     Main-Is:		Main.hs      Other-modules:-        ToolShed.Test.QuickChecks         ToolShed.Test.Data.Foldable         ToolShed.Test.Data.List         ToolShed.Test.Data.List.Runlength         ToolShed.Test.Data.List.Splits+        ToolShed.Test.Data.Quadruple+        ToolShed.Test.Data.Triple+        ToolShed.Test.QuickChecks+        ToolShed.Test.SelfValidate+        ToolShed.Test.System.Random      Build-depends:         Cabal >= 1.6 && < 2