toolshed 0.16.0.0 → 0.17.0.2
raw patch · 37 files changed
+954/−621 lines, 37 filesdep +HUnitdep +data-default
Dependencies added: HUnit, data-default
Files
- .ghci +1/−0
- README.markdown +14/−4
- changelog.markdown +115/−75
- copyright +1/−1
- src-lib/ToolShed/Data/Array/IArray.hs +47/−0
- src-lib/ToolShed/Data/Foldable.hs +7/−3
- src-lib/ToolShed/Data/List.hs +57/−4
- src-lib/ToolShed/Data/String.hs +45/−0
- src-lib/ToolShed/Defaultable.hs +0/−36
- src-lib/ToolShed/Options.hs +4/−4
- src-lib/ToolShed/SelfValidate.hs +1/−1
- src-lib/ToolShed/System/File.hs +1/−1
- src-lib/ToolShed/System/Random.hs +15/−8
- src-lib/ToolShed/Test/Ix.hs +34/−0
- src-lib/ToolShed/Test/QuickCheck/Arbitrary/Array.hs +7/−2
- src-lib/ToolShed/Test/QuickCheck/Arbitrary/Map.hs +4/−1
- src-lib/ToolShed/Test/QuickCheck/Arbitrary/Set.hs +4/−1
- src-lib/ToolShed/Test/ReversibleIO.hs +25/−2
- src-test/Main.hs +23/−24
- src-test/ToolShed/Test/Data/Foldable.hs +0/−51
- src-test/ToolShed/Test/Data/List.hs +0/−76
- src-test/ToolShed/Test/Data/List/Runlength.hs +0/−36
- src-test/ToolShed/Test/Data/List/Splits.hs +0/−40
- src-test/ToolShed/Test/Data/Quadruple.hs +0/−36
- src-test/ToolShed/Test/Data/Triple.hs +0/−37
- src-test/ToolShed/Test/HUnit/Data/List.hs +67/−0
- src-test/ToolShed/Test/QuickCheck/Data/Foldable.hs +51/−0
- src-test/ToolShed/Test/QuickCheck/Data/List.hs +91/−0
- src-test/ToolShed/Test/QuickCheck/Data/List/Runlength.hs +36/−0
- src-test/ToolShed/Test/QuickCheck/Data/List/Splits.hs +40/−0
- src-test/ToolShed/Test/QuickCheck/Data/Quadruple.hs +36/−0
- src-test/ToolShed/Test/QuickCheck/Data/Triple.hs +37/−0
- src-test/ToolShed/Test/QuickCheck/SelfValidate.hs +81/−0
- src-test/ToolShed/Test/QuickCheck/System/Random.hs +83/−0
- src-test/ToolShed/Test/SelfValidate.hs +0/−77
- src-test/ToolShed/Test/System/Random.hs +0/−83
- toolshed.cabal +27/−18
+ .ghci view
@@ -0,0 +1,1 @@+:set -isrc-lib:src-test:dist/build/autogen -optP-include -optPdist/build/autogen/cabal_macros.h
README.markdown view
@@ -1,18 +1,28 @@-# **ToolShed**.+# **ToolShed** -This is **ToolShed**, a library of unconnected utilities.+[](https://hackage.haskell.org/package/toolshed) [](https://travis-ci.org/functionalley/ToolShed) +This is "**ToolShed**", a library of unconnected utilities.+ ## Installation It can be built and installed using [Cabal](https://www.haskell.org/cabal/users-guide/installing-packages.html). ## License -For information on copying and distributing this package, see the file **LICENSE** in this directory.+For information on copying and distributing this package, see the file "**LICENSE**" in this directory. ## Bug-reporting -Bug-reports should be emailed to <toolshed *at* functionalley *dot* eu>.+Bug-reports should be emailed to <toolshed@functionalley.eu>.++## Testing++The test-suite can be run using:++ cabal configure --enable-tests;+ cabal build;+ cabal test --show-details=always; ## Author
changelog.markdown view
@@ -1,91 +1,131 @@-# 2010-11-18 Dr. Alistair Ward <toolshed at functionalley dot eu>+# 2010-11-18 Dr. Alistair Ward <toolshed@functionalley.eu> ## 0.9.0.0- * First version of the package.+* First version of the package.+ ## 0.10.0.0- * Created **src/ToolShed/** sub-directory & then modified module-names accordingly.- * Removed the module **Pair**, & relocated its only function to the sole caller in the package **Bridge**.- * Added a makefile.- * Qualified identifiers used in error-messages.+* Created sub-directory "**src/ToolShed/**" & then modified module-names accordingly.+* Removed the module "**Pair**", & relocated its only function to the sole caller in the package "**Bridge**".+* Added a makefile.+* Qualified identifiers used in error-messages.+ ## 0.10.0.1- * Tested with ghc-7.0.1, & conditionally replaced use of the package **parallel** with **deepseq**, in the module **TimePure**.+* Tested with **ghc-7.0.1**, & conditionally replaced use of the package "**parallel**" with "**deepseq**", in the module "**TimePure**".+ ## 0.10.1.0- * Added `ToolShed.Arithmetic.nCr`, **ToolShed.Options** & **ToolShed.Package**.+* Added `ToolShed.Arithmetic.nCr`, **ToolShed.Options** & **ToolShed.Package**.+ ## 0.10.2.0- * Renamed package from **ToolShed** to **toolshed**, for compatibility with Debian's *.deb*-format.+* Renamed package "**ToolShed**" to "**toolshed**", for compatibility with Debian's *.deb*-format.+ ## 0.11.0.0- * Added manually controlled **llvm** flag to the *.cabal*-file.- * Removed the module **ToolShed.Package**, for which **Distribution.Package.PackageIdentifier** is a suitable alternative.- * Added **NOINLINE** pragma to each function in module **Unsafe**.- * Relocated `mean` & `nCr` from **ToolShed.Arithmetic**, to the package **factory**.- * Added function `ListPlus.groupComparing`.- * Changed identifier for type-parameters, to better reflect its role.- * Relocated the remaining rather pointless functions from the module **ToolShed.Arithmetic** & deleted it.- * Added module **ToolShed.Defaultable**, & derived class `ToolShed.Options.Options` from it.+* Added manually controlled flag "**llvm**" to the *.cabal*-file.+* Removed the module "**ToolShed.Package**", for which "**Distribution.Package.PackageIdentifier**" is a suitable alternative.+* Added pragma "**NOINLINE**" to each function in module "**Unsafe**".+* Relocated `mean` & `nCr` from **ToolShed.Arithmetic**, to the package "**factory**".+* Added function `ListPlus.groupComparing`.+* Changed identifier for type-parameters, to better reflect its role.+* Relocated the remaining rather pointless functions from the module "**ToolShed.Arithmetic**" & deleted it.+* Added module "**ToolShed.Defaultable**", & derived class `ToolShed.Options.Options` from it.+ ## 0.11.1.0- * Added functions `merge` & `mergeBy` to module **ToolShed.ListPlus** & exported a new type-synonym `ToolShed.ListPlus.ChunkLength`.- * Uploaded to [Hackage](http://hackage.haskell.org/packages/hackage.html).+* Added functions `merge` & `mergeBy` to module "**ToolShed.ListPlus**" & exported a new type-synonym `ToolShed.ListPlus.ChunkLength`.+* Uploaded to [Hackage](http://hackage.haskell.org/package/toolshed).+ ## 0.12.0.0- * Added modules **ToolShed.TimeAction** to measure the CPU-seconds required for an IO-action, & **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`.+* 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`.+ ## 0.13.0.0- * Removed module **ToolShed.Unsafe**.- * Renamed:- **ToolShed.ListPlus** to **ToolShed.Data.List**- **ToolShed.Pair** to **ToolShed.Data.Pair**- **ToolShed.TimeAction** to **ToolShed.System.TimeAction**- **ToolShed.TimePure** to **ToolShed.System.TimePure**- * Migrated **ToolShed.Data.List.RunLengthCode** & associated functions, into a new module **ToolShed.Data.List.Runlength**.- * Migrated **ToolShed.Data.List.Splits** & associated functions, into a new module **ToolShed.Data.List.Splits**.- * Replaced function `ToolShed.Data.List.groupComparing` with the more useful `ToolShed.Data.List.equalityBy`, which can be used with either `Data.List.groupBy` or `Data.List.nubBy`.- * 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 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.- * Removed `ToolShed.Data.Pair.both`.- ` Replaced `System` with `System.Environment` & `System.Exit`.- * Removed dependency on **haskell98**.+* Removed module "**ToolShed.Unsafe**".+* Renamed:+ + **ToolShed.ListPlus** to **ToolShed.Data.List**+ + **ToolShed.Pair** to **ToolShed.Data.Pair**+ + **ToolShed.TimeAction** to **ToolShed.System.TimeAction**+ + **ToolShed.TimePure** to **ToolShed.System.TimePure**+* Migrated **ToolShed.Data.List.RunLengthCode** & associated functions, into a new module "**ToolShed.Data.List.Runlength**".+* Migrated **ToolShed.Data.List.Splits** & associated functions, into a new module "**ToolShed.Data.List.Splits**".+* Replaced function `ToolShed.Data.List.groupComparing` with the more useful `ToolShed.Data.List.equalityBy`, which can be used with either `Data.List.groupBy` or `Data.List.nubBy`.+* 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`,src-lib/ToolShed/Test/ReversibleIO.hs+ + `ToolShed.Data.List.findConvergenceBy`,+ + `ToolShed.Data.List.findConvergence`,+ + `ToolShed.Data.List.gather`.+* 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.+* Removed `ToolShed.Data.Pair.both`.+` Replaced `System` with `System.Environment` & `System.Exit`.+* Removed dependency on **haskell98**.+ ## 0.14.0.0- * 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**.- * 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 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**.+* 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**.+* 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 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`.+* Refactored **ToolShed.Test.QuickChecks**.+* Added type `ToolShed.Data.List.Matches` & function `ToolShed.src-lib/ToolShed/Test/ReversibleIO.hsData.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 option "**--version**".+* Corrected the output of `Main.main.optDescrList.printVersion`.+ ## 0.15.0.1- * Tested with **haskell-platform-2013.2.0.0**.- * Replaced preprocessor-directives with **build-depends** constraints in the *.cabal*-file.- * In module **ToolShed.System.File**, replaced `Control.Exception.throw` with `Control.Exception.throwIO`.- * Replaced all instances of `(<$>)` with `fmap` to avoid ambiguity between **Control.Applicative** & **Prelude** which (from **base-4.8**) also exports this symbol.+* Tested with **haskell-platform-2013.2.0.0**.+* Replaced preprocessor-directives with **build-depends** constraints in the *.cabal*-file.+* In module "**ToolShed.System.File**", replaced `Control.Exception.throw` with `Control.Exception.throwIO`.+* Replaced all instances of `(<$>)` with `fmap` to avoid ambigusrc-lib/ToolShed/Test/ReversibleIO.hsity between modules "**Control.Applicative**" & "**Prelude**" which (from package "**base-4.8**") also exports this symbol.+ ## 0.16.0.0- * Corrected the copyright dates in **Main**.- * Renamed module **ToolShed.Test.QuickCheck.Arbitrary.ArrayElem** to **ToolShed.Test.QuickCheck.Arbitrary.Array**, overwriting the module originally of that name which pointlessly defined an instance of `Test.QuickCheck.Arbitrary` for an array with an unbounded index.- * Added **Default-language**-specification to the *.cabal*-file.- * Added file **README.markdown**.- * Converted this file to markdown-format.- * Replaced `System.Exit.exitWith System.Exit.ExitSuccess` with `System.Exit.exitSuccess`.- * Added module **Test.QuickCheck.Result**.- * Moved the entry-point to the test-suite from **Main.hs** to **Test.hs** to integrate with **cabal**.- * Partitioned the source-files into **src-lib** & **src-test** directories, & referenced them individually from the *.cabal*-file to avoid repeated compilation.+* Corrected the copyright dates in **Main**.+* Renamed module "**ToolShed.Test.QuickCheck.Arbitrary.ArrayElem**" to "**ToolShed.Test.QuickCheck.Arbitrary.Array**", overwriting the module originally of that name which pointlessly defined an instance of `Test.QuickCheck.Arbitrary` for an array with an unbounded index.+* Added **Default-language**-specification to the *.cabal*-file.+* Added file "**README.markdown**".+* Converted this file to markdown-format.+* Replaced `System.Exit.exitWith System.Exit.ExitSuccess` with `System.Exit.exitSuccess`.+* Added module "**Test.QuickCheck.Result**".+* Moved the entry-point to the test-suite from module "**Main.hs**" to "**Test.hs**" to integrate with **cabal**.+* Partitioned the source-files into directories "**src-lib**" & "**src-test**", & referenced them individually from the *.cabal*-file to avoid repeated compilation. +## 0.17.0.0+* Corrected the markdown-syntax in this file.+* Reverted to calling "**error**" rather than "**Control.Monad.fail**", since the **String**-argument for the latter is discarded in **Monad**-implementations other than **IO**.+* Uploaded to [GitHub](https://github.com/functionalley/ToolShed.git).+* Simplified file **src-test/Main.hs**.+* Relaxed test **prop_shuffleDistribution** in module **ToolShed.Test.System.Random**.+* Added file **.travis.yml** to control testing by <https://docs.travis-ci.com>.+* Added file **.ghci**.+* Removed module **ToolShed.Defaultable**, since **Data.Default** is a drop-in replacement.+* Added functions **ToolShed.Test.ReversibleIO.readTrailingGarbage** & **ToolShed.Test.ReversibleIO.readPrependedWhiteSpace**.+* Added function **ToolShed.Data.List.interleave** with corresponding quickcheck-tests.+* Added module **ToolShed.Test.Ix** to facilitate testing instances of class **Data.Array.IArray.Ix**.+* Added module **ToolShed.Data.Array.IArray**.+* Added function **ToolShed.Data.String.deTab**.+* Generalised function **ToolShed.System.Random.select** to accept any **Data.Foldable.Foldable** rather than merely a list, & to return **Maybe** rather than an error on receipt of null.+* Added fuzzy matching function **ToolShed.Data.List.measureJaroDistance** & associated **HUnit** & **Quickcheck** tests.+* Tested with **ghc-8.0.1**.+## 0.17.0.1+* Modified Travis-CI configuration.+## 0.17.0.2+* Removed **-prof** from profiling-flags in Cabal-configuration.
copyright view
@@ -1,5 +1,5 @@ Author:- Dr. Alistair Ward <toolshed at functionalley dot eu>.+ Dr. Alistair Ward <toolshed@functionalley.eu>. Copyright: Copyright (C) 2010-2013 Dr. Alistair Ward. All Rights Reserved.
+ src-lib/ToolShed/Data/Array/IArray.hs view
@@ -0,0 +1,47 @@+{-+ 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@]++ * Additions to module "Data.Array.IArray".+-}++module ToolShed.Data.Array.IArray(+-- * Functions+ adjust+) where++import qualified Data.Array.IArray+import Data.Array.IArray((!), (//))++-- | Update a single element of the specified array.+adjust :: (+ Data.Array.IArray.Ix i,+ Data.Array.IArray.IArray a e+ )+ => (e -> e) -- ^ Mutator.+ -> i -- ^ Index.+ -> a i e+ -> a i e+adjust mutator i array = array // [+ (+ i,+ mutator $ array ! i+ ) -- Pair.+ ]
src-lib/ToolShed/Data/Foldable.hs view
@@ -37,14 +37,18 @@ * The groups are returned in ascending order, whilst their elements remain in their original order. -}-gatherBy :: (Data.Foldable.Foldable f, Ord b) => (a -> b) -> f a -> [[a]]+gatherBy+ :: (Data.Foldable.Foldable foldable, Ord b)+ => (a -> b) -- ^ Function to apply before testing for equality.+ -> foldable a -- ^ The input data.+ -> [[a]] gatherBy f = Data.Map.elems . Data.Foldable.foldr (uncurry (Data.Map.insertWith (++)) . (f &&& return {-to List-monad-})) Data.Map.empty -- | A specific instance of 'gatherBy'.-gather :: (Data.Foldable.Foldable f, Ord a) => f a -> [[a]]+gather :: (Data.Foldable.Foldable foldable, Ord a) => foldable a -> [[a]] gather = gatherBy id -- | Whether the specified collection contains any equal items.-hasDuplicates :: (Data.Foldable.Foldable f, Ord a) => f a -> Bool+hasDuplicates :: (Data.Foldable.Foldable foldable, Ord a) => foldable a -> Bool hasDuplicates = any ((> 1) . length) . gather
src-lib/ToolShed/Data/List.hs view
@@ -1,5 +1,5 @@ {-- Copyright (C) 2010 Dr. Alistair Ward+ Copyright (C) 2010-2015 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@@ -31,7 +31,9 @@ equalityBy, findConvergence, findConvergenceBy,+ interleave, linearise,+ measureJaroDistance, merge, mergeBy, nub',@@ -45,10 +47,11 @@ ) where import qualified Control.Arrow-import Control.Arrow((&&&))+import Control.Arrow((&&&),(***)) import qualified Data.IntSet import qualified Data.List import qualified Data.Set+import qualified Data.Tuple -- | The length of the chunks into which a list is split. type ChunkLength = Int@@ -123,7 +126,7 @@ * 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.+ * N.B.: differs from 'Data.List.permutations', which selects items from a single input list. -} permutations :: [[a]] -> [[a]] permutations = permutationsBy (\_ _ -> True)@@ -150,6 +153,11 @@ linearise [] = [] linearise ((l, r) : remainder) = l : r : linearise remainder -- Recurse. +-- | Interleaves the specified lists, taking the first item from the first list.+interleave :: [a] -> [a] -> [a]+interleave (x : xs) ys = x : interleave ys xs+interleave _ ys = ys+ {- | * Merge two sorted lists, according to the specified order, to product a single sorted list. @@ -172,7 +180,7 @@ {- | * Take until the specified predicate is satisfied; /including/ the item which satisfied it. - * NB: @takeWhile (not . test)@ would return one fewer item.+ * N.B.: @takeWhile (not . test)@ would return one fewer item. -} takeUntil :: (a -> Bool) -- ^ Predicate, used to determine the last item taken.@@ -200,4 +208,49 @@ -- | A specialisation of 'showListWith'. showListWithString :: Show element => (String, String, String) -> [element] -> ShowS showListWithString (startDelimiter, separator, endDelimiter) = foldr (.) (showString endDelimiter) . (showString startDelimiter :) . Data.List.intersperse (showString separator) . map shows++{- |+ * Measures the /distance/ between two lists (typically Strings).++ * The operation is /commutative/; it doesn't matter about the order of the arguments.++ * The result ranges from /0/ when they're completely dissimilar, to /1/ when identical.++ * <https://lingpipe-blog.com/2006/12/13/code-spelunking-jaro-winkler-string-comparison>.+-}+measureJaroDistance :: (Eq a, Fractional distance) => ([a], [a]) -> distance+measureJaroDistance pair+ | uncurry (==) pair = 1+ | nMatches == 0 = 0 -- Guard against divide-by-zero.+ | otherwise = sum [+ fMatches / fromIntegral l,+ fMatches / fromIntegral l',+ 1 - fromIntegral (+ foldr (+ \cc -> if uncurry (==) cc then id else succ+ ) (0 :: Int) $ uncurry zip matchesPair -- Count transpositions; matches which occur in a different order.+ ) / (+ 2 {-compensate for double counting-} * fMatches+ )+ ] / 3 {-normalise: each component of the above sum is in the closed unit interval-}+ where+ l, l' :: Int+ (l, l') = length *** length $ pair++ findMatches :: Eq a => ([a], [a]) -> [a]+ findMatches = uncurry slave . (zip [0 ..] *** zip [0 ..]) where+ slave :: Eq a => [(Int, a)] -> [(Int, a)] -> [a]+ slave [] _ = [] -- There's nothing to match.+ slave _ [] = [] -- Ignore any remaining 'xs', since there's nothing against which to match.+ slave ((i, x) : xs) ys = case span (+ uncurry (||) . (+ (> pred (max l l' `div` 2)) . abs . (i -) *** (x /=)+ ) -- Reject either mismatches, or matches which occur outside a maximum separation.+ ) ys of+ (matchFailures, _ : untested) -> x : slave xs (matchFailures ++ untested) -- Remove the matched datum, so that it can't be matched against again.+ _ -> slave xs ys -- Failed to match 'x' in 'ys'.++ matchesPair@(matches, _) = findMatches &&& findMatches . Data.Tuple.swap $ pair+ nMatches = length matches+ fMatches = fromIntegral nMatches -- Translate to the return-type.
+ src-lib/ToolShed/Data/String.hs view
@@ -0,0 +1,45 @@+{-+ Copyright (C) 2016 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 String-orientated functions.+-}++module ToolShed.Data.String(+-- * Functions+ deTab+) where++-- | Replaces any embedded tab-characters with the appropriate number of spaces.+deTab+ :: Int -- ^ Tab-length.+ -> String+ -> String+deTab tabLength+ | tabLength < 0 = error . showString "ToolShed.Data.String.deTab:\ttab-length=" $ shows tabLength " must be negative."+ | tabLength == 0 = filter (/= '\t')+ | otherwise = slave 0+ where+ slave :: Int -> String -> String+ slave _ [] = [] -- Terminate.+ slave i (c : s) = case c of+ '\t' -> replicate (tabLength - mod i tabLength) ' ' ++ slave 0 s+ '\r' -> c : slave 0 s+ '\n' -> c : slave 0 s+ _ -> c : slave (succ i) s+
− src-lib/ToolShed/Defaultable.hs
@@ -1,36 +0,0 @@-{-- Copyright (C) 2011 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@] A simple interface which data-types with a default-value can implement.--}--module ToolShed.Defaultable(--- * Type-classes- Defaultable(..)-) where---- | An interface to which data which have a default-value can adhere.-class Defaultable a where- defaultValue :: a -- ^ The default value of the data-type.--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-lib/ToolShed/Options.hs view
@@ -1,5 +1,5 @@ {-- Copyright (C) 2011 Dr. Alistair Ward+ Copyright (C) 2011-2015 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@@ -25,8 +25,8 @@ Options(..) ) where -import qualified ToolShed.Defaultable+import qualified Data.Default --- | Similar to the class 'Text.Regex.Base.RegexLike.RegexOptions'.-class ToolShed.Defaultable.Defaultable a => Options a where+-- | The required interface.+class Data.Default.Default a => Options a where blankValue :: a -- ^ The /undefined/ state of the data-type, which may be literal, but could alternatively be a logical starting value.
src-lib/ToolShed/SelfValidate.hs view
@@ -23,7 +23,7 @@ module ToolShed.SelfValidate( -- * Type-classes SelfValidator(..),--- ** Functions+-- * Functions getFirstError, extractErrors ) where
src-lib/ToolShed/System/File.hs view
@@ -102,5 +102,5 @@ case reads fileContents of [(x, _)] -> return {-to IO-monad-} (filePath, x) -- CAVEAT: discards any unconsumed text.- _ -> fail $ "ToolShed.System.File.fromFile:\tfailed to parse file=" ++ show filePath+ _ -> error . showString "ToolShed.System.File.fromFile:\tfailed to parse file=" $ shows filePath "."
src-lib/ToolShed/System/Random.hs view
@@ -31,6 +31,7 @@ ) where import qualified Control.Arrow+import qualified Data.Foldable import qualified Data.Sequence import Data.Sequence((><), ViewL((:<))) import qualified System.Random@@ -40,7 +41,7 @@ randomGens = uncurry (:) . Control.Arrow.second randomGens {-recurse-} . System.Random.split {- |- * Shuffles the specified finite list, using the /Fisher-Yates/ algorithm; <http://en.wikipedia.org/wiki/Fisher-Yates_shuffle>.+ * Shuffles the specified finite list, using the /Fisher-Yates/ algorithm; <https://en.wikipedia.org/wiki/Fisher-Yates_shuffle>. * The resulting list has the same length and constituents as the original; only the order has changed. @@ -64,14 +65,20 @@ * 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+generateSelection :: System.Random.RandomGen randomGen => randomGen -> [a] -> Maybe [a]+generateSelection _ [] = Nothing+generateSelection _ [x] = Just $ repeat x -- Not strictly necessary, but more efficient.+generateSelection randomGen l = Just . map (l !!) $ System.Random.randomRs (0, pred $ length l) randomGen --- | Return a randomly selected element from the specified list.-select :: System.Random.RandomGen randomGen => randomGen -> [a] -> a-select randomGen = head . generateSelection randomGen+-- | Return a randomly selected element from those provided.+select :: (+ Data.Foldable.Foldable foldable,+ System.Random.RandomGen randomGen+ )+ => randomGen+ -> foldable a+ -> Maybe a+select randomGen = fmap head . generateSelection randomGen . Data.Foldable.toList {- | * Generate an infinite list of data, each independently selected random instances of the specified /bounded/ type.
+ src-lib/ToolShed/Test/Ix.hs view
@@ -0,0 +1,34 @@+{-+ Copyright (C) 2015 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@] Facilities testing of custom implementations of 'Data.Array.IArray.Ix'.+-}++module ToolShed.Test.Ix(+-- * Functions+-- ** Predicates+ index+) where++import qualified Data.Array.IArray++-- | Checks that implementations of Data.Array.IArray.Ix satisfy rules.+index :: (Bounded a, Data.Array.IArray.Ix a) => a -> Bool+index x = Data.Array.IArray.range (minBound, maxBound) !! Data.Array.IArray.index (minBound, maxBound) x == x+
src-lib/ToolShed/Test/QuickCheck/Arbitrary/Array.hs view
@@ -31,7 +31,12 @@ import qualified Data.Array.IArray import qualified Test.QuickCheck -instance (Bounded i, Data.Array.IArray.Ix i, Enum i, Test.QuickCheck.Arbitrary e) => Test.QuickCheck.Arbitrary (Data.Array.IArray.Array i e) where- arbitrary = (Data.Array.IArray.array bounds . zip [minBound .. maxBound]) `fmap` Test.QuickCheck.vector (succ $ fromEnum (snd bounds) - fromEnum (fst bounds)) where+instance (+ Bounded i,+ Data.Array.IArray.Ix i,+ Enum i,+ Test.QuickCheck.Arbitrary e+ ) => Test.QuickCheck.Arbitrary (Data.Array.IArray.Array i e) where+ arbitrary = Data.Array.IArray.listArray bounds `fmap` Test.QuickCheck.vector (succ $ fromEnum (snd bounds) - fromEnum (fst bounds)) where bounds = (minBound, maxBound)
src-lib/ToolShed/Test/QuickCheck/Arbitrary/Map.hs view
@@ -1,4 +1,5 @@ {-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE CPP #-} {- Copyright (C) 2012-2015 Dr. Alistair Ward @@ -18,16 +19,18 @@ {- | [@AUTHOR@] Dr. Alistair Ward - [@DESCRIPTION@] Implements 'Test.QuickCheck.Arbitrary' for 'Data.Map.Map'.+ [@DESCRIPTION@] Implements 'Test.QuickCheck.Arbitrary' for 'Data.Map.Map'; which was subsequently implemented in "QuickCheck-2.8.2". [@EXAMPLE@] @Test.QuickCheck.sample (Test.QuickCheck.arbitrary :: Test.QuickCheck.Gen.Gen (Data.Map.Map Char Int))@ -} module ToolShed.Test.QuickCheck.Arbitrary.Map() where +#if !MIN_VERSION_QuickCheck(2,8,2) import qualified Data.Map import qualified Test.QuickCheck instance (Ord k, Test.QuickCheck.Arbitrary k, Test.QuickCheck.Arbitrary v) => Test.QuickCheck.Arbitrary (Data.Map.Map k v) where arbitrary = Data.Map.fromList `fmap` Test.QuickCheck.arbitrary {-[(k, v)]-}+#endif
src-lib/ToolShed/Test/QuickCheck/Arbitrary/Set.hs view
@@ -1,4 +1,5 @@ {-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE CPP #-} {- Copyright (C) 2012-2015 Dr. Alistair Ward @@ -18,16 +19,18 @@ {- | [@AUTHOR@] Dr. Alistair Ward - [@DESCRIPTION@] Implements 'Test.QuickCheck.Arbitrary' for 'Data.Set.Set'.+ [@DESCRIPTION@] Implements 'Test.QuickCheck.Arbitrary' for 'Data.Set.Set'; which was subsequently implemented in "QuickCheck-2.8.2". [@EXAMPLE@] @Test.QuickCheck.sample (Test.QuickCheck.arbitrary :: Test.QuickCheck.Gen.Gen (Data.Set.Set Int))@ -} module ToolShed.Test.QuickCheck.Arbitrary.Set() where +#if !MIN_VERSION_QuickCheck(2,8,2) import qualified Data.Set import qualified Test.QuickCheck instance (Ord k, Test.QuickCheck.Arbitrary k) => Test.QuickCheck.Arbitrary (Data.Set.Set k) where arbitrary = Data.Set.fromList `fmap` Test.QuickCheck.arbitrary {-[k]-}+#endif
src-lib/ToolShed/Test/ReversibleIO.hs view
@@ -19,7 +19,7 @@ [@DESCRIPTION@] - * Facilities testing of custom implementations of 'Read' & 'Show'.+ * Facilitates testing of custom implementations of 'Read' & 'Show'. * CAVEAT: it doesn't actually do any IO. -}@@ -27,9 +27,32 @@ module ToolShed.Test.ReversibleIO( -- * Functions -- ** Predicates- isReversible+ isReversible,+ readPrependedWhiteSpace,+ readTrailingGarbage ) where -- | Checks that composing 'read' & 'show' is equivalent to the identity. isReversible :: (Eq r, Read r, Show r) => r -> Bool isReversible r = read (show r) == r++-- | Checks whether 'read' can skip prepended white space; 'isReversible' is a prerequisite.+readPrependedWhiteSpace :: (Eq r, Read r, Show r) => r -> Bool+readPrependedWhiteSpace r = read (" \t\r\n" ++ show r) == r++-- | Checks whether 'read' both copes with garbage following the valid input-data, & leaves it unchanged.+readTrailingGarbage :: (+ Eq a,+ Read a,+ Show a+ )+ => (Char -> Bool) -- ^ Whether a character of garbage might reasonably be confused with valid data, & therefore should be dropped.+ -> a -- ^ The datum to be written & read.+ -> String -- ^ The text to follow the written datum.+ -> Bool+readTrailingGarbage predicate x s = let+ s' = dropWhile predicate s+ in case reads $ shows x s' of+ [pair] -> pair == (x, s')+ _ -> False+
src-test/Main.hs view
@@ -24,35 +24,34 @@ module Main(main) where -import Control.Arrow((***)) import qualified Control.Monad+import qualified Test.HUnit import qualified System.Exit-import qualified ToolShed.Test.Data.Foldable as Test.Data.Foldable-import qualified ToolShed.Test.Data.List as Test.Data.List-import qualified ToolShed.Test.Data.List.Runlength as Test.Data.List.Runlength-import qualified ToolShed.Test.Data.List.Splits as Test.Data.List.Splits-import qualified ToolShed.Test.Data.Quadruple as Test.Data.Quadruple-import qualified ToolShed.Test.Data.Triple as Test.Data.Triple-import qualified ToolShed.Test.QuickCheck.Result as Test.QuickCheck.Result-import qualified ToolShed.Test.SelfValidate as Test.SelfValidate-import qualified ToolShed.Test.System.Random as Test.System.Random+import qualified ToolShed.Test.HUnit.Data.List as Test.HUnit.Data.List+import qualified ToolShed.Test.QuickCheck.Data.Foldable as Test.QuickCheck.Data.Foldable+import qualified ToolShed.Test.QuickCheck.Data.List as Test.QuickCheck.Data.List+import qualified ToolShed.Test.QuickCheck.Data.List.Runlength as Test.QuickCheck.Data.List.Runlength+import qualified ToolShed.Test.QuickCheck.Data.List.Splits as Test.QuickCheck.Data.List.Splits+import qualified ToolShed.Test.QuickCheck.Data.Quadruple as Test.QuickCheck.Data.Quadruple+import qualified ToolShed.Test.QuickCheck.Data.Triple as Test.QuickCheck.Data.Triple+import qualified ToolShed.Test.QuickCheck.Result as Test.QuickCheck.Result+import qualified ToolShed.Test.QuickCheck.SelfValidate as Test.QuickCheck.SelfValidate+import qualified ToolShed.Test.QuickCheck.System.Random as Test.QuickCheck.System.Random -- | Entry-point. main :: IO ()-main = mapM_ (- snd {-exit-status-} . (- putStrLn . (++ ":") *** (- >>= (`Control.Monad.unless` System.Exit.exitFailure) . all Test.QuickCheck.Result.isSuccessful- )- )+main = mapM_ Test.HUnit.runTestTT [+ Test.HUnit.Data.List.testCases+ ] >> mapM_ (+ (`Control.Monad.unless` System.Exit.exitFailure) . all Test.QuickCheck.Result.isSuccessful =<< ) [- ("Data.Foldable", Test.Data.Foldable.results),- ("Data.List", Test.Data.List.results),- ("Data.List.Runlength", Test.Data.List.Runlength.results),- ("Data.List.Splits", Test.Data.List.Splits.results),- ("Data.Quadruple", Test.Data.Quadruple.results),- ("Data.Triple", Test.Data.Triple.results),- ("SelfValidate", Test.SelfValidate.results),- ("System.Random", Test.System.Random.results)+ Test.QuickCheck.Data.Foldable.results,+ Test.QuickCheck.Data.List.results,+ Test.QuickCheck.Data.List.Runlength.results,+ Test.QuickCheck.Data.List.Splits.results,+ Test.QuickCheck.Data.Quadruple.results,+ Test.QuickCheck.Data.Triple.results,+ Test.QuickCheck.SelfValidate.results,+ Test.QuickCheck.System.Random.results ]
− src-test/ToolShed/Test/Data/Foldable.hs
@@ -1,51 +0,0 @@-{-- Copyright (C) 2012-2015 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.Foldable".--}--module ToolShed.Test.Data.Foldable(--- * Constants- results-) where--import qualified Data.List-import qualified Data.Ord-import qualified Data.Set-import qualified ToolShed.Data.Foldable-import qualified ToolShed.Data.List-import qualified Test.QuickCheck---- | The constant test-results for this data-type.-results :: IO [Test.QuickCheck.Result]-results = sequence [- Test.QuickCheck.quickCheckResult prop_gatherSet,- Test.QuickCheck.quickCheckResult prop_gatherBy- ] where- prop_gatherSet :: Int -> Test.QuickCheck.Property- prop_gatherSet n = Test.QuickCheck.label "prop_gatherSet" . (== l) . concat . ToolShed.Data.Foldable.gather $ Data.Set.fromDistinctAscList l where- l = [0 .. n `mod` 1024]-- prop_gatherBy :: [Int] -> Test.QuickCheck.Property- prop_gatherBy l = Test.QuickCheck.label "prop_gatherBy" $ map Data.List.sort (- ToolShed.Data.Foldable.gatherBy even l- ) == (- map Data.List.sort . Data.List.groupBy (ToolShed.Data.List.equalityBy even) $ Data.List.sortBy (Data.Ord.comparing even) l- )-
− src-test/ToolShed/Test/Data/List.hs
@@ -1,76 +0,0 @@-{-- Copyright (C) 2012-2015 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.List".--}--module ToolShed.Test.Data.List(--- * Constants- results-) where--import qualified Data.List-import qualified ToolShed.Data.List-import qualified Test.QuickCheck-import Test.QuickCheck((==>))---- | The constant test-results for this data-type.-results :: IO [Test.QuickCheck.Result]-results = sequence [- Test.QuickCheck.quickCheckResult prop_chunk,- Test.QuickCheck.quickCheckResult prop_findConvergence,- Test.QuickCheck.quickCheckResult prop_linearise,- Test.QuickCheck.quickCheckResult prop_merge,- Test.QuickCheck.quickCheckResult prop_nub,- Test.QuickCheck.quickCheckResult prop_permutations,- Test.QuickCheck.quickCheckResult prop_permutations',- Test.QuickCheck.quickCheckResult prop_permutationsBy,- Test.QuickCheck.quickCheckResult prop_permutationsBy'- ] where- prop_chunk :: Int -> [Int] -> Test.QuickCheck.Property- prop_chunk i l = Test.QuickCheck.label "prop_chunk" $ concat (ToolShed.Data.List.chunk (succ $ abs i) l) == l-- prop_findConvergence :: Int -> Test.QuickCheck.Property- prop_findConvergence = Test.QuickCheck.label "prop_findConvergence" . (== 0) . ToolShed.Data.List.findConvergence . iterate (fst . (`quotRem` 2))-- 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-- prop_merge :: [Int] -> [Int] -> Test.QuickCheck.Property- prop_merge x y = Test.QuickCheck.label "prop_merge" $ ToolShed.Data.List.merge (Data.List.sort x) (Data.List.sort y) == Data.List.sort (x ++ y)-- 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, 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']-
− src-test/ToolShed/Test/Data/List/Runlength.hs
@@ -1,36 +0,0 @@-{-- Copyright (C) 2012-2015 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.List.Runlength".--}--module ToolShed.Test.Data.List.Runlength(--- * Constants- results-) where--import qualified ToolShed.Data.List.Runlength-import qualified Test.QuickCheck---- | The constant test-results for this data-type.-results :: IO [Test.QuickCheck.Result]-results = mapM Test.QuickCheck.quickCheckResult [prop_runLength] where- prop_runLength :: [Int] -> Test.QuickCheck.Property- prop_runLength l = Test.QuickCheck.label "prop_runLength" $ ToolShed.Data.List.Runlength.decode (ToolShed.Data.List.Runlength.encode l) == l-
− src-test/ToolShed/Test/Data/List/Splits.hs
@@ -1,40 +0,0 @@-{-- Copyright (C) 2012-2015 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.List.Splits".--}--module ToolShed.Test.Data.List.Splits(--- * Constants- results-) where--import Control.Arrow((***))-import qualified Data.Tuple-import qualified ToolShed.Data.List.Splits-import qualified Test.QuickCheck-import Test.QuickCheck((==>))---- | The constant test-results for this data-type.-results :: IO [Test.QuickCheck.Result]-results = mapM Test.QuickCheck.quickCheckResult [prop_splitsFrom] where- prop_splitsFrom :: Int -> [Int] -> Test.QuickCheck.Property- prop_splitsFrom i l = not (null l) ==> Test.QuickCheck.label "prop_splitsFrom" $ take n (ToolShed.Data.List.Splits.splitsLeftFrom index l) == take n (map (Data.Tuple.swap . (reverse *** reverse)) . ToolShed.Data.List.Splits.splitsRightFrom (length l - index) $ reverse l) where- index = i `mod` length l- n = succ index
− src-test/ToolShed/Test/Data/Quadruple.hs
@@ -1,36 +0,0 @@-{-- Copyright (C) 2013-2015 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(--- * Constants- results-) where--import qualified Test.QuickCheck-import qualified ToolShed.Data.Quadruple---- | The constant test-results for this data-type.-results :: IO [Test.QuickCheck.Result]-results = mapM Test.QuickCheck.quickCheckResult [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-test/ToolShed/Test/Data/Triple.hs
@@ -1,37 +0,0 @@-{-- Copyright (C) 2013-2015 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(--- * Constants- results-) where--import qualified Test.QuickCheck-import qualified ToolShed.Data.Triple---- | The constant test-results for this data-type.-results :: IO [Test.QuickCheck.Result]-results = mapM Test.QuickCheck.quickCheckResult [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-test/ToolShed/Test/HUnit/Data/List.hs view
@@ -0,0 +1,67 @@+{-+ Copyright (C) 2016 Dr. Alistair Ward++ This file is part of ToolShed.++ ToolShed 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.++ ToolShed 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 ToolShed. If not, see <http://www.gnu.org/licenses/>.+-}+{- |+ [@AUTHOR@] Dr. Alistair Ward++ [@DESCRIPTION@]++ * Static tests.++ * <http://www.census.gov/srd/papers/pdf/rrs2006-02.pdf>+-}++module ToolShed.Test.HUnit.Data.List(+-- * Constants+ testCases+-- * Functions+-- approxDistance+) where++import qualified Test.HUnit+import Test.HUnit((~:),(~?=))+import qualified ToolShed.Data.List as Data.List++approxDistance :: (String, String) -> Double+approxDistance pair = (/ fromIntegral precision) . fromInteger . round $ (fromIntegral precision * Data.List.measureJaroDistance pair :: Rational) where+ precision :: Int+ precision = 1000++-- | Check the sanity of the implementation, by validating a list of static test-cases.+testCases :: Test.HUnit.Test+testCases = Test.HUnit.test [+ "ToolShed.Data.List.measureJaroDistance 1 failed." ~: Data.List.measureJaroDistance ("DIXON", "DICKSONX") ~?= (4 / 5 + 4 / 8 + 1 :: Rational) / 3,+ "ToolShed.Data.List.measureJaroDistance 2 failed." ~: Data.List.measureJaroDistance ("JELLYFISH", "SMELLYFISH") ~?= (8 / 9 + 8 / 10 + 1 :: Rational) / 3,+ "ToolShed.Data.List.measureJaroDistance 3 failed." ~: approxDistance ("SHACKLEFORD", "SHACKELFORD") ~?= 0.970,+ "ToolShed.Data.List.measureJaroDistance 4 failed." ~: approxDistance ("DUNNINGHAM", "CUNNIGHAM") ~?= 0.896,+ "ToolShed.Data.List.measureJaroDistance 5 failed." ~: approxDistance ("NICHLESON", "NICHULSON") ~?= 0.926,+ "ToolShed.Data.List.measureJaroDistance 6 failed." ~: approxDistance ("JONES", "JOHNSON") ~?= 0.790,+ "ToolShed.Data.List.measureJaroDistance 7 failed." ~: approxDistance ("MASSEY", "MASSIE") ~?= 0.889,+ "ToolShed.Data.List.measureJaroDistance 8 failed." ~: approxDistance ("ABROMS", "ABRAMS") ~?= 0.889,+ "ToolShed.Data.List.measureJaroDistance 9 failed." ~: Data.List.measureJaroDistance ("HARDIN", "MARTINEZ") ~?= (4 / 6 + 4 / 8 + 1 :: Rational) / 3, -- CAVEAT: cited paper says this value should be zero ?!+ "ToolShed.Data.List.measureJaroDistance 10 failed." ~: Data.List.measureJaroDistance ("ITMAN", "SMITH") ~?= (1 / 5 + 1 / 5 + 1 :: Rational) / 3, -- CAVEAT: cited paper says this value should be zero ?!+ "ToolShed.Data.List.measureJaroDistance 11 failed." ~: approxDistance ("JERALDINE", "GERALDINE") ~?= 0.926,+ "ToolShed.Data.List.measureJaroDistance 12 failed." ~: approxDistance ("MARHTA", "MARTHA") ~?= 0.944,+ "ToolShed.Data.List.measureJaroDistance 13 failed." ~: approxDistance ("MICHELLE", "MICHAEL") ~?= 0.869,+ "ToolShed.Data.List.measureJaroDistance 14 failed." ~: approxDistance ("JULIES", "JULIUS") ~?= 0.889,+ "ToolShed.Data.List.measureJaroDistance 15 failed." ~: approxDistance ("TANYA", "TONYA") ~?= 0.867,+ "ToolShed.Data.List.measureJaroDistance 16 failed." ~: approxDistance ("DWAYNE", "DUANE") ~?= 0.822,+ "ToolShed.Data.List.measureJaroDistance 17 failed." ~: approxDistance ("SEAN", "SUSAN") ~?= 0.783,+ "ToolShed.Data.List.measureJaroDistance 18 failed." ~: approxDistance ("JON", "JOHN") ~?= 0.917,+ "ToolShed.Data.List.measureJaroDistance 19 failed." ~: Data.List.measureJaroDistance ("JON", "JAN") ~?= (2 / 3 + 2 / 3 + 1 :: Rational) / 3 -- CAVEAT: cited paper says this value should be zero ?!+ ]
+ src-test/ToolShed/Test/QuickCheck/Data/Foldable.hs view
@@ -0,0 +1,51 @@+{-+ Copyright (C) 2012-2015 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.Foldable".+-}++module ToolShed.Test.QuickCheck.Data.Foldable(+-- * Constants+ results+) where++import qualified Data.List+import qualified Data.Ord+import qualified Data.Set+import qualified ToolShed.Data.Foldable+import qualified ToolShed.Data.List+import qualified Test.QuickCheck++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results = sequence [+ Test.QuickCheck.quickCheckResult prop_gatherSet,+ Test.QuickCheck.quickCheckResult prop_gatherBy+ ] where+ prop_gatherSet :: Int -> Test.QuickCheck.Property+ prop_gatherSet n = Test.QuickCheck.label "prop_gatherSet" . (== l) . concat . ToolShed.Data.Foldable.gather $ Data.Set.fromDistinctAscList l where+ l = [0 .. n `mod` 1024]++ prop_gatherBy :: [Int] -> Test.QuickCheck.Property+ prop_gatherBy l = Test.QuickCheck.label "prop_gatherBy" $ map Data.List.sort (+ ToolShed.Data.Foldable.gatherBy even l+ ) == (+ map Data.List.sort . Data.List.groupBy (ToolShed.Data.List.equalityBy even) $ Data.List.sortBy (Data.Ord.comparing even) l+ )+
+ src-test/ToolShed/Test/QuickCheck/Data/List.hs view
@@ -0,0 +1,91 @@+{-+ Copyright (C) 2012-2016 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.List".+-}++module ToolShed.Test.QuickCheck.Data.List(+-- * Constants+ results+) where++import qualified Data.List+import qualified Data.Tuple+import qualified ToolShed.Data.List+import qualified Test.QuickCheck+import Test.QuickCheck((==>))++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results = sequence [+ Test.QuickCheck.quickCheckResult prop_chunk,+ Test.QuickCheck.quickCheckResult prop_findConvergence,+ Test.QuickCheck.quickCheckResult prop_linearise,+ Test.QuickCheck.quickCheckResult prop_merge,+ Test.QuickCheck.quickCheckResult prop_nub,+ Test.QuickCheck.quickCheckResult prop_permutations,+ Test.QuickCheck.quickCheckResult prop_permutations',+ Test.QuickCheck.quickCheckResult prop_permutationsBy,+ Test.QuickCheck.quickCheckResult prop_permutationsBy',+ Test.QuickCheck.quickCheckResult prop_interleave,+ Test.QuickCheck.quickCheckResult prop_interleave',+ Test.QuickCheck.quickCheckResult prop_jaroDistanceCommutative,+ Test.QuickCheck.quickCheckResult prop_jaroDistanceRange+ ] where+ prop_chunk :: Int -> [Int] -> Test.QuickCheck.Property+ prop_chunk i l = Test.QuickCheck.label "prop_chunk" $ concat (ToolShed.Data.List.chunk (succ $ abs i) l) == l++ prop_findConvergence :: Int -> Test.QuickCheck.Property+ prop_findConvergence = Test.QuickCheck.label "prop_findConvergence" . (== 0) . ToolShed.Data.List.findConvergence . iterate (fst . (`quotRem` 2))++ 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++ prop_merge :: [Int] -> [Int] -> Test.QuickCheck.Property+ prop_merge x y = Test.QuickCheck.label "prop_merge" $ ToolShed.Data.List.merge (Data.List.sort x) (Data.List.sort y) == Data.List.sort (x ++ y)++ 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, 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_interleave :: [Int] -> [Int] -> Test.QuickCheck.Property+ prop_interleave xs ys = Test.QuickCheck.label "prop_interleave" $ length (ToolShed.Data.List.interleave xs ys) == length xs + length ys++ prop_interleave' :: [Int] -> [Int] -> Test.QuickCheck.Property+ prop_interleave' xs ys = not (null xs) ==> Test.QuickCheck.label "prop_interleave'" $ head (ToolShed.Data.List.interleave xs ys) == head xs++ prop_jaroDistanceCommutative, prop_jaroDistanceRange :: (String, String) -> Test.QuickCheck.Property+ prop_jaroDistanceCommutative pair = Test.QuickCheck.label "prop_jaroDistanceCommutative" $ (ToolShed.Data.List.measureJaroDistance pair :: Rational) == ToolShed.Data.List.measureJaroDistance (Data.Tuple.swap pair)+ prop_jaroDistanceRange pair = Test.QuickCheck.label "prop_jaroDistanceRange" $ all ($ (ToolShed.Data.List.measureJaroDistance pair :: Rational)) [(>= 0), (<= 1)]+
+ src-test/ToolShed/Test/QuickCheck/Data/List/Runlength.hs view
@@ -0,0 +1,36 @@+{-+ Copyright (C) 2012-2015 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.List.Runlength".+-}++module ToolShed.Test.QuickCheck.Data.List.Runlength(+-- * Constants+ results+) where++import qualified ToolShed.Data.List.Runlength+import qualified Test.QuickCheck++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results = mapM Test.QuickCheck.quickCheckResult [prop_runLength] where+ prop_runLength :: [Int] -> Test.QuickCheck.Property+ prop_runLength l = Test.QuickCheck.label "prop_runLength" $ ToolShed.Data.List.Runlength.decode (ToolShed.Data.List.Runlength.encode l) == l+
+ src-test/ToolShed/Test/QuickCheck/Data/List/Splits.hs view
@@ -0,0 +1,40 @@+{-+ Copyright (C) 2012-2015 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.List.Splits".+-}++module ToolShed.Test.QuickCheck.Data.List.Splits(+-- * Constants+ results+) where++import Control.Arrow((***))+import qualified Data.Tuple+import qualified ToolShed.Data.List.Splits+import qualified Test.QuickCheck+import Test.QuickCheck((==>))++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results = mapM Test.QuickCheck.quickCheckResult [prop_splitsFrom] where+ prop_splitsFrom :: Int -> [Int] -> Test.QuickCheck.Property+ prop_splitsFrom i l = not (null l) ==> Test.QuickCheck.label "prop_splitsFrom" $ take n (ToolShed.Data.List.Splits.splitsLeftFrom index l) == take n (map (Data.Tuple.swap . (reverse *** reverse)) . ToolShed.Data.List.Splits.splitsRightFrom (length l - index) $ reverse l) where+ index = i `mod` length l+ n = succ index
+ src-test/ToolShed/Test/QuickCheck/Data/Quadruple.hs view
@@ -0,0 +1,36 @@+{-+ Copyright (C) 2013-2015 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.QuickCheck.Data.Quadruple(+-- * Constants+ results+) where++import qualified Test.QuickCheck+import qualified ToolShed.Data.Quadruple++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results = mapM Test.QuickCheck.quickCheckResult [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-test/ToolShed/Test/QuickCheck/Data/Triple.hs view
@@ -0,0 +1,37 @@+{-+ Copyright (C) 2013-2015 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.QuickCheck.Data.Triple(+-- * Constants+ results+) where++import qualified Test.QuickCheck+import qualified ToolShed.Data.Triple++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results = mapM Test.QuickCheck.quickCheckResult [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-test/ToolShed/Test/QuickCheck/SelfValidate.hs view
@@ -0,0 +1,81 @@+{-# LANGUAGE CPP #-}+{-+ Copyright (C) 2012-2015 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.SelfValidate".+-}++module ToolShed.Test.QuickCheck.SelfValidate(+-- * Constants+ results,+-- * Types+-- ** Data-types+-- Primes+) where++import qualified Data.Foldable+import qualified Data.List+import qualified Data.Map+import qualified Data.Set+import qualified Test.QuickCheck+import Test.QuickCheck((==>))+import qualified ToolShed.SelfValidate as SelfValidate++#if !MIN_VERSION_QuickCheck(2,8,2)+import ToolShed.Test.QuickCheck.Arbitrary.Map()+import ToolShed.Test.QuickCheck.Arbitrary.Set()+#endif++-- | A test-type.+newtype Primes = MkPrimes Int deriving (Eq, Ord, Show)++instance SelfValidate.SelfValidator Primes where+ getErrors (MkPrimes i) = SelfValidate.extractErrors [+ (any ((== 0) . (i `rem`)) [2,3,5], "Composite; " ++ show i),+ (i < 0, "Negative; " ++ show i),+ (i `elem` [0, 1], "Excluded; " ++ show i)+ ]++instance Test.QuickCheck.Arbitrary Primes where+ arbitrary = MkPrimes `fmap` Test.QuickCheck.elements [negate limit .. limit] where limit = pred $ 7 * 7++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results = sequence [+ Test.QuickCheck.quickCheckResult prop_list,+ Test.QuickCheck.quickCheckResult prop_list',+ Test.QuickCheck.quickCheckResult prop_set,+ Test.QuickCheck.quickCheckResult prop_map+ ] where+ prop_list, prop_list' :: [Primes] -> Test.QuickCheck.Property+ prop_list l = not (null l) ==> Test.QuickCheck.label "prop_list" $ SelfValidate.getErrors (head l) `Data.List.isPrefixOf` SelfValidate.getErrors l+ prop_list' l = Test.QuickCheck.label "prop_list'" $ all (+ (`elem` map SelfValidate.getErrors l) . SelfValidate.getErrors+ ) l++ prop_set :: Data.Set.Set Primes -> Test.QuickCheck.Property+ prop_set s = Test.QuickCheck.label "prop_set" $ Data.Foldable.all (+ (`Data.Set.isSubsetOf` Data.Set.fromList (SelfValidate.getErrors s)) . Data.Set.fromList . SelfValidate.getErrors+ ) s++ prop_map :: Data.Map.Map Int Primes -> Test.QuickCheck.Property+ prop_map m = Test.QuickCheck.label "prop_map" $ Data.Foldable.all (+ (`Data.Set.isSubsetOf` Data.Set.fromList (SelfValidate.getErrors m)) . Data.Set.fromList . SelfValidate.getErrors+ ) m+
+ src-test/ToolShed/Test/QuickCheck/System/Random.hs view
@@ -0,0 +1,83 @@+{-+ Copyright (C) 2013-2015 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.QuickCheck.System.Random(+-- * Constants+ results,+-- * Functions+-- getMean,+-- getStandardDeviation+) 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 foldable, Real r, Fractional result) => foldable 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 foldable, Functor foldable, Real r) => foldable r -> Double+getStandardDeviation x = sqrt . getMean $ fmap ((^ (2 :: Int)) . (+ negate (getMean x :: Rational)) . toRational) x++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results = sequence [+ Test.QuickCheck.quickCheckResult prop_shuffle,+ Test.QuickCheck.quickCheckResult 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 16 {-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+
− src-test/ToolShed/Test/SelfValidate.hs
@@ -1,77 +0,0 @@-{-- Copyright (C) 2012-2015 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.SelfValidate".--}--module ToolShed.Test.SelfValidate(--- * Constants- results,--- * Types--- ** Data-types--- Primes-) where--import qualified Data.Foldable-import qualified Data.List-import qualified Data.Map-import qualified Data.Set-import qualified Test.QuickCheck-import Test.QuickCheck((==>))-import qualified ToolShed.SelfValidate as SelfValidate-import ToolShed.Test.QuickCheck.Arbitrary.Map()-import ToolShed.Test.QuickCheck.Arbitrary.Set()---- | A test-type.-newtype Primes = MkPrimes Int deriving (Eq, Ord, Show)--instance SelfValidate.SelfValidator Primes where- getErrors (MkPrimes i) = SelfValidate.extractErrors [- (any ((== 0) . (i `rem`)) [2,3,5], "Composite; " ++ show i),- (i < 0, "Negative; " ++ show i),- (i `elem` [0, 1], "Excluded; " ++ show i)- ]--instance Test.QuickCheck.Arbitrary Primes where- arbitrary = MkPrimes `fmap` Test.QuickCheck.elements [negate limit .. limit] where limit = pred $ 7 * 7---- | The constant test-results for this data-type.-results :: IO [Test.QuickCheck.Result]-results = sequence [- Test.QuickCheck.quickCheckResult prop_list,- Test.QuickCheck.quickCheckResult prop_list',- Test.QuickCheck.quickCheckResult prop_set,- Test.QuickCheck.quickCheckResult prop_map- ] where- prop_list, prop_list' :: [Primes] -> Test.QuickCheck.Property- prop_list l = not (null l) ==> Test.QuickCheck.label "prop_list" $ SelfValidate.getErrors (head l) `Data.List.isPrefixOf` SelfValidate.getErrors l- prop_list' l = Test.QuickCheck.label "prop_list'" $ all (- (`elem` map SelfValidate.getErrors l) . SelfValidate.getErrors- ) l-- prop_set :: Data.Set.Set Primes -> Test.QuickCheck.Property- prop_set s = Test.QuickCheck.label "prop_set" $ Data.Foldable.all (- (`Data.Set.isSubsetOf` Data.Set.fromList (SelfValidate.getErrors s)) . Data.Set.fromList . SelfValidate.getErrors- ) s-- prop_map :: Data.Map.Map Int Primes -> Test.QuickCheck.Property- prop_map m = Test.QuickCheck.label "prop_map" $ Data.Foldable.all (- (`Data.Set.isSubsetOf` Data.Set.fromList (SelfValidate.getErrors m)) . Data.Set.fromList . SelfValidate.getErrors- ) m-
− src-test/ToolShed/Test/System/Random.hs
@@ -1,83 +0,0 @@-{-- Copyright (C) 2013-2015 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(--- * Constants- results,--- * Functions--- getMean,--- getStandardDeviation-) 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---- | The constant test-results for this data-type.-results :: IO [Test.QuickCheck.Result]-results = sequence [- Test.QuickCheck.quickCheckResult prop_shuffle,- Test.QuickCheck.quickCheckResult 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
@@ -14,7 +14,7 @@ -- along with ToolShed. If not, see <http://www.gnu.org/licenses/>. Name: toolshed-Version: 0.16.0.0+Version: 0.17.0.2 Cabal-version: >= 1.10 Copyright: (C) 2010-2015 Dr. Alistair Ward License: GPL@@ -25,17 +25,22 @@ Build-type: Simple Description: Ill-defined unrelated utilities used by other packages from <http://functionalley.eu> Category: Utils-Tested-with: GHC == 7.4, GHC == 7.6, GHC == 7.8, GHC == 7.10+Tested-with: GHC == 7.4, GHC == 7.6, GHC == 7.10.1, GHC == 8.0.1 Homepage: http://functionalley.eu-Maintainer: mailto <colon> toolshed <at> functionalley <dot> eu-Bug-reports: mailto <colon> toolshed <at> functionalley <dot> eu+Maintainer: mailto:toolshed@functionalley.eu+Bug-reports: mailto:toolshed@functionalley.eu -- None of these files are needed at run-time. Extra-source-files:+ .ghci changelog.markdown copyright README.markdown +source-repository head+ type: git+ location: https://github.com/functionalley/ToolShed+ -- Enable using: 'cabal configure -f llvm'. flag llvm Description: Whether the 'llvm' compiler-backend has been installed and is required for code-generation.@@ -44,24 +49,26 @@ Library Default-language: Haskell2010- GHC-options: -Wall -O2 -fno-warn-tabs+ GHC-options: -O2 -Wall -fno-warn-tabs Hs-source-dirs: src-lib Exposed-modules: ToolShed.Data.Foldable+ ToolShed.Data.Array.IArray ToolShed.Data.List ToolShed.Data.List.Runlength ToolShed.Data.List.Splits ToolShed.Data.Pair ToolShed.Data.Quadruple+ ToolShed.Data.String ToolShed.Data.Triple- ToolShed.Defaultable ToolShed.Options ToolShed.SelfValidate ToolShed.System.File ToolShed.System.Random ToolShed.System.TimeAction ToolShed.System.TimePure+ ToolShed.Test.Ix ToolShed.Test.QuickCheck.Arbitrary.Array ToolShed.Test.QuickCheck.Arbitrary.Map ToolShed.Test.QuickCheck.Arbitrary.Set@@ -74,6 +81,7 @@ array, base == 4.*, containers >= 0.4.2.0,+ data-default, deepseq >= 1.1, directory, filepath,@@ -81,14 +89,14 @@ random if impl(ghc >= 7.4.1)- GHC-prof-options: -prof -fprof-auto -fprof-cafs+ GHC-prof-options: -fprof-auto -fprof-cafs else- GHC-prof-options: -prof -auto-all -caf-all+ GHC-prof-options: -auto-all -caf-all if impl(ghc >= 7.0) && flag(llvm) GHC-options: -fllvm -Test-Suite quickCheck+Test-Suite test Default-language: Haskell2010 GHC-options: -Wall -fno-warn-tabs Hs-source-dirs: src-test@@ -97,20 +105,21 @@ -- Required for 'cabal sdist'. Other-modules:- 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.SelfValidate- ToolShed.Test.System.Random+ ToolShed.Test.HUnit.Data.List+ ToolShed.Test.QuickCheck.Data.Foldable+ ToolShed.Test.QuickCheck.Data.List+ ToolShed.Test.QuickCheck.Data.List.Runlength+ ToolShed.Test.QuickCheck.Data.List.Splits+ ToolShed.Test.QuickCheck.Data.Quadruple+ ToolShed.Test.QuickCheck.Data.Triple+ ToolShed.Test.QuickCheck.SelfValidate+ ToolShed.Test.QuickCheck.System.Random Build-depends: base == 4.*, containers >= 0.4.2.0,+ HUnit, QuickCheck >= 2.2, random, toolshed-