diff --git a/README.markdown b/README.markdown
new file mode 100644
--- /dev/null
+++ b/README.markdown
@@ -0,0 +1,30 @@
+# **FishFood**.
+
+This is **FishFood**, an application which determines the distribution in sizes of the specified files.
+
+## Installation
+
+It can be built and installed using [Cabal](https://www.haskell.org/cabal/users-guide/installing-packages.html).
+
+## Documentation
+
+The directory **man/** contains the documentation.
+
+## License
+
+For information on copying and distributing this package, see the file **LICENSE** in this directory.
+
+## Bug-reporting
+
+Bug-reports should be emailed to <fishfood *at* functionalley *dot* eu>.
+
+## Testing
+
+The test-suite can be run using:
+	cabal configure --enable-tests
+	cabal build
+	cabal test --show-details=always
+
+## Author
+
+This application is written and maintained by Dr. Alistair Ward.
diff --git a/changelog b/changelog
deleted file mode 100644
--- a/changelog
+++ /dev/null
@@ -1,23 +0,0 @@
-2013-07-16 Dr. Alistair Ward <fishfood at functionalley dot eu>
-
-0.0.0.1
-	* First version of the package.
-0.0.0.2
-	* Added 'man/man1/fishfood.1' & 'fishfood.spec' to the distribution.
-0.0.1.0
-	* Migrated all but the I/O, from "Main" to a new module "FishFood.Profiler".
-	* Added module "FishFood.Test", containing "Test.QuickCheck"-implementation.
-	* Added Command-line options; '--deriveProbabilityMassFunction', '--binSizeRatio', '--runQuickChecks'.
-0.0.1.1
-	* Added files to build .deb to 'fishfood.cabal'.
-0.0.1.2
-	* Added '--runQuickChecks' to 'man/man1/fishfood.1' & corrected typo.
-	* Improved the syntax of 'verbosity' in the usage-message.
-	* Tested with 'haskell-platform-2013.2.0.0'.
-0.0.1.3
-	* In module "FishFood.Data.File", replaced 'Control.Exception.throw' with 'Control.Exception.throwIO'.
-	* Either replaced instances of '(<$>)' with 'fmap' to avoid ambiguity between "Control.Applicative" & "Prelude" which (from 'base-4.8') also exports this symbol, or hid the symbol when importing the "Prelude"..
-	* In module "Main", redirected version-message to stderr.
-0.0.1.4
-	* Added the compiler to the output returned for the command-line option "version".
-	* In module "FishFood.Data.File.hs", replaced the use of the package "unix" with the package "directory", for compatibility with Windows.
diff --git a/changelog.markdown b/changelog.markdown
new file mode 100644
--- /dev/null
+++ b/changelog.markdown
@@ -0,0 +1,31 @@
+# 2013-07-16 Dr. Alistair Ward <fishfood at functionalley dot eu>
+
+## 0.0.0.1
+	* First version of the package.
+## 0.0.0.2
+	* Added **man/man1/fishfood.1** & *.spec*-file to the distribution.
+## 0.0.1.0
+	* Migrated all but the I/O, from **Main** to a new module **FishFood.Profiler**.
+	* Added module **FishFood.Test**, containing **Test.QuickCheck**-implementation.
+	* Added Command-line options; **--deriveProbabilityMassFunction**, **--binSizeRatio**, **--runQuickChecks**.
+## 0.0.1.1
+	* Added files to build *.deb* to the *.cabal*-file.
+## 0.0.1.2
+	* Added **--runQuickChecks** to **man/man1/fishfood.1** & corrected typo.
+	* Improved the syntax of **verbosity** in the usage-message.
+	* Tested with **haskell-platform-2013.2.0.0**.
+## 0.0.1.3
+	* In module **FishFood.Data.File**, replaced `Control.Exception.throw` with `Control.Exception.throwIO`.
+	* Either replaced instances of `(<$>)` with `fmap` to avoid ambiguity between **Control.Applicative** & **Prelude** which (from **base-4.8**) also exports this symbol, or hid the symbol when importing the **Prelude**..
+	* In module **Main**, redirected version-message to stderr.
+## 0.0.1.4
+	* Added the compiler to the output returned for the command-line option **version**.
+	* In module **FishFood.Data.File.hs**, replaced the use of the package **unix** with the package **directory**, for compatibility with Windows.
+## 0.0.1.5
+	* 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`.
+	* Moved the entry-point to the test-suite from **Main.hs** to **Test.hs**, both to integrate with **cabal** & to minimise the dependencies of the executable.
+	* Partitioned the source-files into **src-lib**, **src-exe**, & **src-test** directories, & referenced them individually from the *.cabal*-file to avoid repeated compilation.
+	* Used **CPP** to control the import of symbols from **Control.Applicative**.
diff --git a/debian/DEBIAN/control b/debian/DEBIAN/control
--- a/debian/DEBIAN/control
+++ b/debian/DEBIAN/control
@@ -1,11 +1,10 @@
 Package:	fishfood
-Version:	0.0.1.4-1
+Version:	0.0.1.5-1
 Section:	utils
 Priority:	optional
-#Architecture:	i386
 Architecture:	amd64
 Depends:	libc6
-Installed-size:	2252
+Installed-size:	2082
 Maintainer:	Dr. Alistair Ward <fishfood at functionalley dot eu>
 Provides:
 Homepage:	http://functionalley.eu
diff --git a/fishfood.cabal b/fishfood.cabal
--- a/fishfood.cabal
+++ b/fishfood.cabal
@@ -1,54 +1,92 @@
--- Package-properties
-Name:			fishfood
-Version:		0.0.1.4
-Cabal-Version:		>= 1.6
-Copyright:		(C) 2013-2015 Dr. Alistair Ward
-License:		GPL
-License-file:		LICENSE
-Author:			Dr. Alistair Ward
-Stability:		Unstable interface, incomplete features.
-Synopsis:		Calculates file-size frequency-distribution.
-Build-Type:		Simple
-Description:		Counts the number of files in a set of bins, each of which holds only those files which fall within a specific size-interval.
-Category:		Utils
-Tested-With:		GHC == 7.4, GHC == 7.6, GHC == 7.10
-Homepage:		http://functionalley.eu
-Maintainer:		fishfood <at> functionalley <dot> eu
-Bug-reports:		fishfood <at> functionalley <dot> eu
-Data-files:
-Extra-Source-Files:	changelog changelog.Debian copyright debian/DEBIAN/control fishfood.spec man/man1/fishfood.1
+-- This file is part of FishFood.
+--
+-- FishFood 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.
+--
+-- FishFood 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 FishFood.  If not, see <http://www.gnu.org/licenses/>.
 
--- Turn on using: 'runhaskell ./Setup.hs configure -f llvm'.
+Name:		fishfood
+Version:	0.0.1.5
+Cabal-version:	>= 1.10
+Copyright:	(C) 2013-2015 Dr. Alistair Ward
+License:	GPL
+License-file:	LICENSE
+Author:		Dr. Alistair Ward
+Stability:	stable
+Synopsis:	Calculates file-size frequency-distribution.
+Build-type:	Simple
+Description:	Counts the number of files in a set of bins, each of which holds only those files which fall within a specific size-interval.
+Category:	Utils
+Tested-with:	GHC == 7.4, GHC == 7.6, GHC == 7.8, GHC == 7.10
+Homepage:	http://functionalley.eu
+Maintainer:	mailto <colon> fishfood <at> functionalley <dot> eu
+Bug-reports:	mailto <colon> fishfood <at> functionalley <dot> eu
+
+-- None of these files are needed at run-time.
+Extra-source-files:
+    changelog.markdown
+    changelog.Debian
+    copyright
+    debian/DEBIAN/control
+    fishfood.spec
+    man/man1/fishfood.1
+    README.markdown
+
+-- Enable using: 'cabal configure -f llvm'.
 flag llvm
     Description:	Whether the 'llvm' compiler-backend has been installed and is required for code-generation.
-    manual:		True
-    default:		False
+    Manual:		True
+    Default:		False
 
-Executable fishfood
-    hs-source-dirs:	src
-    Main-Is:		Main.hs
-    Other-modules:
-        FishFood.Data.CommandOptions,
-        FishFood.Data.File,
+Library
+    Default-language:	Haskell2010
+    GHC-options:	-Wall -fno-warn-tabs
+    Hs-source-dirs:	src-lib
+
+    Exposed-modules:
+        FishFood.Data.CommandOptions
+        FishFood.Data.File
         FishFood.Data.Verbosity
         FishFood.Profiler
-        FishFood.Test.Data.CommandOptions
-        FishFood.Test.Data.Verbosity
-        FishFood.Test.Profiler
-        FishFood.Test.QuickChecks
 
     Build-depends:
         base == 4.*,
-        Cabal >= 1.6 && < 2,
+        Cabal >= 1.10,
         containers,
         directory,
         factory >= 0.2.0.5,
         mtl,
-        QuickCheck,
-        toolshed >= 0.13
+        toolshed >= 0.16
 
+    if impl(ghc >= 7.4.1)
+        GHC-prof-options:	-prof -fprof-auto -fprof-cafs
+    else
+        GHC-prof-options:	-prof -auto-all -caf-all
+
+    if impl(ghc >= 7.0) && flag(llvm)
+        GHC-options:	-fllvm
+
+Executable fishfood
+    Default-language:	Haskell2010
     GHC-options:	-Wall -fno-warn-tabs
+    Hs-source-dirs:	src-exe
+    Main-is:		Main.hs
 
+    Build-depends:
+        base == 4.*,
+        Cabal >= 1.10,
+        fishfood,
+        mtl,
+        toolshed >= 0.16
+
     if impl(ghc >= 7.4.1)
         GHC-prof-options:	-prof -fprof-auto -fprof-cafs
     else
@@ -59,4 +97,26 @@
 
         if flag(llvm)
             GHC-options:	-fllvm
+
+Test-Suite quickCheck
+    Default-language:	Haskell2010
+    GHC-options:	-Wall -fno-warn-tabs
+    Hs-source-dirs:	src-test
+    Main-is:		Main.hs
+    Type:		exitcode-stdio-1.0
+
+-- Required for 'cabal sdist'.
+    Other-modules:
+        FishFood.Test.Data.CommandOptions
+        FishFood.Test.Data.Verbosity
+        FishFood.Test.Profiler
+
+    Build-depends:
+        base == 4.*,
+        Cabal >= 1.10,
+        containers,
+        fishfood,
+        mtl,
+        QuickCheck,
+        toolshed >= 0.16
 
diff --git a/fishfood.spec b/fishfood.spec
--- a/fishfood.spec
+++ b/fishfood.spec
@@ -1,4 +1,4 @@
-# Copyright (C) 2013-2014 Dr. Alistair Ward
+# 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
@@ -15,51 +15,53 @@
 
 %define package		%name-%version
 %define tarBall		%package.tar.gz
-%define _bindir		%prefix/bin
 %define _sharedir	%prefix/share
-%define _docdir		%_sharedir/doc/%package
+%define _docdir		%_sharedir/doc/%name
 %define _mandir		%_sharedir/man
 
 Summary:	Calculates file-size frequency-distribution.
 Name:		fishfood
-Version:	0.0.1.4
+Version:	0.0.1.5
 Release:	1
 License:	GPLv3
-#From '/usr/share/doc/packages/rpm/GROUPS'.
+# From '/usr/share/doc/packages/rpm/GROUPS'.
 Group:		Applications/File
 Source0:	http://functionalley.eu/Downloads/sdist/%tarBall
 URL:		http://functionalley.eu
 Prefix:		/usr
-BuildRequires:	ghc
+BuildRequires:	haskell-platform
 
 %description
 Counts the number of files in a set of bins, each of which holds only those files which fall within a specific size-interval.
 
 %prep
-#NB: we've changed directory to %_builddir
-(cd $OLDPWD && runhaskell Setup sdist) && tar -zxf $OLDPWD/dist/%tarBall	#Make a source-distribution & unpack it into the build-directory.
-cd '%package/' && runhaskell Setup configure --user --prefix=%prefix		#Configure to use the user's personal package-database & to generate an appropriate "Paths" module.
+# NB: CWD has changed to %_builddir
+echo 'package="%package", prefix="%prefix", _builddir="%_builddir", buildroot="%buildroot"'
+(cd $OLDPWD && cabal sdist) && tar -zxf $OLDPWD/dist/%tarBall	# Make a source-distribution & unpack it into the build-directory.
+cd '%package/' && cabal configure --user --prefix='%prefix' --docdir='%_docdir'	# Tell cabal to use the user's personal package-database, to generate an appropriate "Paths" module, & where to place the documentation.
 
 %build
-cd '%package/' && runhaskell Setup build	#Descend into the source-distribution and build according to the previously established configuration.
+cd '%package/' && cabal build	# Descend into the source-distribution and build according to the previously established configuration.
 
 %install
-cd '%package/'					#Descend into the build-directory.
-runhaskell Setup copy --destdir=%buildroot	#Install the package in the target-directory.
-mkdir -p -- '%buildroot%_docdir' && mv changelog copyright LICENSE '%buildroot%_docdir/'
+cd '%package/'	# Descend into the build-directory.
+cabal copy --destdir='%buildroot'	# Install the built package in the target-directory.
+mkdir -p -- '%buildroot%_docdir' && mv 'changelog.markdown' 'copyright' 'README.markdown' '%buildroot%_docdir/'	# 'LICENSE' has already been copied by cabal.
 mkdir -p -- '%buildroot%_mandir' && mv 'man/man1' '%buildroot%_mandir/'
+rm -rf -- '%buildroot%prefix/lib/'	# The library isn't a deliverable.
 
 %clean
-make --directory='%package' clobber
-rm -rf -- '%_builddir/%package/' '%buildroot'
+rm -rf -- '%_builddir/%package/' '%buildroot/'	# Only the '.rpm' is required.
 
 %files
-%attr(0755, root, root)		%_bindir/%name
-%attr(0644, root, root)	%doc	%_docdir/changelog
+%attr(0755, root, root)		%prefix/bin/%name
+%attr(0644, root, root)	%doc	%_docdir/changelog.markdown
 %attr(0644, root, root)	%doc	%_docdir/copyright
 %attr(0644, root, root)	%doc	%_docdir/LICENSE
+%attr(0644, root, root)	%doc	%_docdir/README.markdown
 %attr(0644, root, root)	%doc	%_mandir/man1/%name.1.gz
 
 %changelog
 * Tue Jul 16 2013	Alistair Ward	<fishfood at functionalley dot eu>	0.0.0.2-1
 First cut.
+
diff --git a/man/man1/fishfood.1 b/man/man1/fishfood.1
--- a/man/man1/fishfood.1
+++ b/man/man1/fishfood.1
@@ -32,10 +32,6 @@
 .TP
 \fB-?\fR, \fB--help\fR
 Displays help & then exits.
-.SS Test
-.TP
-\fB-q\fR, \fB--runQuickChecks\fR
-Tests the implementation, by validating some invariant properties using arbitrary data; & then exits.
 .SS File-paths
 .TP
 If \fIFile-path\fR is a single hyphen-minus (\fB-\fR), then the list of file-paths will be read from standard-input. Only plain files are acceptable; no directories, symlinks, sockets, ...
@@ -140,7 +136,7 @@
 Written by Dr. Alistair Ward.
 .SH BUGS
 .SS "REPORTING BUGS"
-Report bugs to \fBfishfood\fR \fIat\fR \fBfunctionalley\fR \fIdot\fR \fBeu\fR
+Report bugs to <\fBfishfood\fR \fIat\fR \fBfunctionalley\fR \fIdot\fR \fBeu\fR>.
 .SH COPYRIGHT
 Copyright \(co 2013-2015 Dr. Alistair Ward
 .PP
diff --git a/src-exe/Main.hs b/src-exe/Main.hs
new file mode 100644
--- /dev/null
+++ b/src-exe/Main.hs
@@ -0,0 +1,179 @@
+{-# LANGUAGE CPP #-}
+{-
+	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@]
+
+	* Contains the entry-point of the application.
+
+	* Processes the command-line arguments.
+
+	* Delegates the task to "Profiler".
+-}
+
+module Main(main) where
+
+import qualified	Control.Monad
+import qualified	Control.Monad.Writer
+import qualified	Data.List
+import qualified	Data.Maybe
+import qualified	Data.Version
+import qualified	Distribution.Package
+import qualified	Distribution.Text
+import qualified	Distribution.Version
+import qualified	FishFood.Data.CommandOptions	as Data.CommandOptions
+import qualified	FishFood.Data.File		as Data.File
+import qualified	FishFood.Data.Verbosity		as Data.Verbosity
+import qualified	FishFood.Profiler		as Profiler
+import qualified	Paths_fishfood			as Paths	-- Either local stub, or package-instance autogenerated by 'Setup.hs build'.
+import qualified	System.Console.GetOpt		as G
+import qualified	System.Environment
+import qualified	System.Exit
+import qualified	System.Info
+import qualified	System.IO
+import qualified	System.IO.Error
+import qualified	ToolShed.Data.List
+import qualified	ToolShed.Defaultable
+import qualified	ToolShed.SelfValidate
+
+#if !MIN_VERSION_base(4,8,0)
+import	Control.Applicative((<$>), (<*>))
+#endif
+
+-- | Define the concrete type of command-options.
+type CommandOptions	= Data.CommandOptions.CommandOptions Double
+
+-- | Used to thread user-defined command-line options, though the list of functions which implement them.
+type CommandLineAction	= CommandOptions -> IO CommandOptions	-- Supplied as the type-argument to 'G.OptDescr'.
+
+-- | On failure to parse the specified string, returns an explanatory error.
+read' :: Read a => String -> String -> a
+read' errorMessage s	= case reads s of
+	[(x, "")]	-> x
+	_		-> error $ errorMessage ++ show s
+
+-- | On failure to parse a command-line argument, returns an explanatory error.
+readCommandArg :: Read a => String -> a
+readCommandArg	= read' "failed to parse command-line argument "
+
+-- | Reads a bounded integral from the command-line, guarding against overflow.
+readBoundedIntegral :: Integral i => String -> i
+readBoundedIntegral s
+	| fromIntegral bounded /= unbounded	= error $ "integral value exceeds permissible bounds; " ++ show unbounded ++ "."
+	| otherwise				= bounded
+	where
+		unbounded	= readCommandArg s
+		bounded		= fromInteger unbounded
+
+{- |
+	* Parses the command-line options, which over-ride default values.
+
+	* Any arguments which follow known options, are interpreted as file-names.
+
+	* If the specified file-name is /-/, then the actual file-names are read from /standard-input/, to augment any other non-options specified.
+-}
+main :: IO ()
+main	= do
+	progName	<- System.Environment.getProgName
+
+	let
+		defaultCommandOptions :: CommandOptions
+		defaultCommandOptions	= ToolShed.Defaultable.defaultValue
+
+		optDescrList :: [G.OptDescr CommandLineAction]
+		optDescrList	= [
+--				 String	[String]				(G.ArgDescr CommandLineAction)				String
+			G.Option "?"	["help"]				(G.NoArg $ const printUsage)				"Display this help, & then exit.",
+			G.Option ""	["verbosity"]				(
+				setVerbosity `G.ReqArg` ToolShed.Data.List.showListWith listDelimiters Data.Verbosity.range ""
+
+			)														("Define the log-level; default '" ++ show (Data.CommandOptions.getVerbosity defaultCommandOptions) ++ "'."
+			),
+			G.Option "v"	["version"]				(G.NoArg $ const printVersion)				"Print version-information, & then exit.",
+			G.Option "s"	["binSizeIncrement"]			(setBinSizeIncrement `G.ReqArg` "<Int>")		"The constant size-increase in the arithmetic sequence of bins into which the byte-sizes of files are categorised; defaulting to one standard-deviation.",
+			G.Option "r"	["binSizeRatio"]			(setBinSizeRatio `G.ReqArg` "<Float>")			"The constant size-ratio in the geometric sequence of bins into which the byte-sizes of files are categorised; an alternative to 'binSizeIncrement'.",
+			G.Option "p"	["deriveProbabilityMassFunction"]	(setDeriveProbabilityMassFunction `G.OptArg` "<Bool>")	("Whether to derive the \"Probability mass function\" rather than the \"Frequency-distribution\"; default '" ++ show (Data.CommandOptions.getDeriveProbabilityMassFunction defaultCommandOptions) ++ "'."),
+			G.Option "d"	["nDecimalDigits"]			(setNDecimalDigits `G.ReqArg` "<Int>")			("The precision to which fractional auxiliary data is displayed; default " ++ show (Data.CommandOptions.getNDecimalDigits defaultCommandOptions) ++ ".")
+		 ] where
+			listDelimiters	= ('(', '|', ')')
+
+			setBinSizeIncrement, setBinSizeRatio, setNDecimalDigits, setVerbosity :: String -> CommandLineAction
+			setBinSizeIncrement arg			= return {-to IO-monad-} . Data.CommandOptions.setBinSizeIncrement (readCommandArg arg)
+			setBinSizeRatio arg			= return {-to IO-monad-} . Data.CommandOptions.setBinSizeRatio (readCommandArg arg)
+			setNDecimalDigits arg commandOptions	= return {-to IO-monad-} commandOptions { Data.CommandOptions.getNDecimalDigits = readBoundedIntegral arg }
+			setVerbosity arg commandOptions		= return {-to IO-monad-} commandOptions { Data.CommandOptions.getVerbosity = readCommandArg arg }
+
+			setDeriveProbabilityMassFunction :: Maybe String -> CommandLineAction
+			setDeriveProbabilityMassFunction arg commandOptions	= return {-to IO-monad-} commandOptions { Data.CommandOptions.getDeriveProbabilityMassFunction = Data.Maybe.maybe True readCommandArg arg }
+
+			printVersion, printUsage :: IO CommandOptions
+			printVersion	= System.IO.hPutStrLn System.IO.stderr (
+				Distribution.Text.display packageIdentifier ++ "\n\nCompiled by " ++ show compiler ++ ".\n\nCopyright (C) 2013-2015 " ++ 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.exitSuccess	where
+				packageIdentifier :: Distribution.Package.PackageIdentifier
+				packageIdentifier	= Distribution.Package.PackageIdentifier {
+					Distribution.Package.pkgName	= Distribution.Package.PackageName progName,	-- CAVEAT: coincidentally.
+					Distribution.Package.pkgVersion	= Distribution.Version.Version (Data.Version.versionBranch Paths.version) []
+				}
+
+				author, compiler :: String
+				author		= "Dr. Alistair Ward"
+				compiler	= System.Info.compilerName ++ "-" ++ Data.List.intercalate "." (map show $ Data.Version.versionBranch System.Info.compilerVersion)
+
+			printUsage	= System.IO.hPutStrLn System.IO.stderr ("Usage:\t" ++ G.usageInfo progName optDescrList ++ "  [<File-path> ...]") >> System.Exit.exitSuccess
+
+	args	<- System.Environment.getArgs
+
+	case G.getOpt G.RequireOrder optDescrList args of
+		(commandLineActions, nonOptions, [{-errors-}])	-> do
+			commandOptions	<- Data.List.foldl' (>>=) (return {-to IO-monad-} ToolShed.Defaultable.defaultValue) commandLineActions
+
+			if not $ ToolShed.SelfValidate.isValid commandOptions
+				then fail $ ToolShed.SelfValidate.getFirstError commandOptions
+				else if null nonOptions
+					then fail "zero file-paths specified"
+					else let
+						standardInputProxy	= "-"
+					in do
+						filePaths	<- if standardInputProxy `elem` nonOptions
+							then let
+								getFilePaths :: IO [String]
+								getFilePaths	= do
+									eof	<- System.IO.isEOF
+
+									if eof
+										then return {-to IO-monad-} []
+										else {-more to read-} (:) <$> getLine <*> getFilePaths {-recurse-}
+							in do
+								filePaths	<- (filter (/= standardInputProxy) nonOptions ++) <$> getFilePaths
+
+								if null filePaths
+									then fail "zero file-paths"
+									else return filePaths
+							else {-real fileNames-} return {-to IO-monad-} nonOptions
+
+						Control.Monad.when (Data.CommandOptions.getVerbosity commandOptions == maxBound) $ System.IO.hPrint System.IO.stderr filePaths	-- CAVEAT: potentially very long.
+
+						(fileSizeDistribution, statistics)	<- Control.Monad.Writer.runWriter . Profiler.calculateFileSizeDistribution commandOptions <$> mapM Data.File.findSize (Data.List.nub filePaths)
+
+						Control.Monad.when (Data.CommandOptions.getVerbosity commandOptions > ToolShed.Defaultable.defaultValue) $ mapM_ (System.IO.hPutStrLn System.IO.stderr) statistics
+
+						putStrLn $ Profiler.formatFileSizeDistribution commandOptions fileSizeDistribution
+		(_, _, errors)	-> System.IO.Error.ioError . System.IO.Error.userError $ concatMap init {-chop-} errors
+
diff --git a/src-lib/FishFood/Data/CommandOptions.hs b/src-lib/FishFood/Data/CommandOptions.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/FishFood/Data/CommandOptions.hs
@@ -0,0 +1,113 @@
+{-
+	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 options for program-operation.
+
+	* Defines an appropriate default value, which is expected to be over-ridden on the command-line.
+
+	* Self-validates.
+-}
+
+module FishFood.Data.CommandOptions(
+-- * Types
+-- ** Type-synonyms
+	BinSizeDelta,
+-- ** Data-types
+	CommandOptions(
+--		MkCommandOptions,
+		getBinSizeDelta,
+		getDeriveProbabilityMassFunction,
+		getNDecimalDigits,
+		getVerbosity
+	),
+-- * Functions
+-- ** Constructors
+	mkCommandOptions,
+-- ** Mutators
+	setBinSizeIncrement,
+	setBinSizeRatio
+) where
+
+import qualified	Data.Maybe
+import qualified	Distribution.Verbosity
+import qualified	FishFood.Data.File	as Data.File
+import qualified	ToolShed.Defaultable
+import qualified	ToolShed.SelfValidate
+
+-- | Either an arithmetic size-increase for which there's a default, or a geometric size-ratio.
+type BinSizeDelta ratio	= Either (Maybe Data.File.FileSize) ratio
+
+-- | Declares a record to contain command-line options.
+data CommandOptions ratio	= MkCommandOptions {
+	getBinSizeDelta				:: BinSizeDelta ratio,			-- ^ Either the arithmetic size-increase (defaulting to one standard-deviation), or the geometric size-ratio, of the sequence of bins into which files are categorized.
+	getDeriveProbabilityMassFunction	:: Bool,				-- ^ Whether to derive the "Probability mass function" rather than the "Frequency-distribution".
+	getNDecimalDigits			:: Int,					-- ^ The precision to which fractional data is displayed.
+	getVerbosity				:: Distribution.Verbosity.Verbosity	-- ^ The threshold for ancillary information-output.
+} deriving Show
+
+instance ToolShed.Defaultable.Defaultable (CommandOptions ratio)	where
+	defaultValue	= MkCommandOptions {
+		getBinSizeDelta				= Left Nothing,	-- Interpreted as one standard-deviation.
+		getDeriveProbabilityMassFunction	= False,
+		getNDecimalDigits			= 3,
+		getVerbosity				= Distribution.Verbosity.normal
+	}
+
+instance (Num ratio, Ord ratio, Show ratio) => ToolShed.SelfValidate.SelfValidator (CommandOptions ratio)	where
+	getErrors commandOptions@MkCommandOptions {
+		getBinSizeDelta				= binSizeDelta,
+		getDeriveProbabilityMassFunction	= deriveProbabilityMassFunction,
+		getNDecimalDigits			= nDecimalDigits
+	} = map snd $ filter fst [
+		(
+			either (Data.Maybe.maybe False (<= 0)) (<= 1) binSizeDelta,
+			"either the bin-size's arithmetic increase must exceed zero, or it's geometric ratio must exceed one; " ++ show commandOptions ++ "."
+		), (
+			deriveProbabilityMassFunction && nDecimalDigits < 1,
+			"the number of decimal digits must exceed zero to adequately represent probabilities; " ++ show commandOptions ++ "."
+		),
+		let
+			maxNDecimalDigits	= floor $ fromIntegral (
+				floatDigits (
+					undefined :: Double	-- CAVEAT: the actual type could be merely 'Float', but that's currently unknown.
+				)
+			 ) * (logBase 10 2 :: Double)
+		in (
+			nDecimalDigits > maxNDecimalDigits,
+			"the number of decimal digits shouldn't exceed " ++ show maxNDecimalDigits ++ "; " ++ show commandOptions ++ "."
+		)
+	 ]
+
+-- | Smart constructor.
+mkCommandOptions :: (Num ratio, Ord ratio, Show ratio) => BinSizeDelta ratio -> Bool -> Int -> Distribution.Verbosity.Verbosity -> CommandOptions ratio
+mkCommandOptions binSizeDelta deriveProbabilityMassFunction nDecimalDigits verbosity
+	| ToolShed.SelfValidate.isValid commandOptions	= commandOptions
+	| otherwise					= error $ "FishFood.Data.CommandOptions.mkCommandOptions:\t" ++ ToolShed.SelfValidate.getFirstError commandOptions
+	where
+		commandOptions	= MkCommandOptions binSizeDelta deriveProbabilityMassFunction nDecimalDigits verbosity
+
+-- | Mutator.
+setBinSizeIncrement :: Data.File.FileSize -> CommandOptions ratio -> CommandOptions ratio
+setBinSizeIncrement fileSize commandOptions	= commandOptions { getBinSizeDelta = Left $ Just fileSize }
+
+-- | Mutator.
+setBinSizeRatio :: ratio -> CommandOptions ratio -> CommandOptions ratio
+setBinSizeRatio ratio commandOptions	= commandOptions { getBinSizeDelta = Right ratio }
diff --git a/src-lib/FishFood/Data/File.hs b/src-lib/FishFood/Data/File.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/FishFood/Data/File.hs
@@ -0,0 +1,60 @@
+{-
+	Copyright (C) 2013-2014 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@]	Allows one to find the size of a file, & to gather statistics on a population.
+-}
+
+module FishFood.Data.File(
+-- * Types
+-- ** Type-synonyms
+	FileSize,
+-- * Functions
+	findSize,
+	getFileSizeStatistics
+) where
+
+import qualified	Control.Exception
+import qualified	Factory.Math.Statistics
+import qualified	System.Directory
+import qualified	System.IO
+import qualified	System.IO.Error
+
+-- | A type-synonym specifically to hold file-sizes (in bytes).
+type FileSize	= Integer	-- Matches the return-type of 'IO.hFileSize'.
+
+-- | Get the size of the specified file.
+findSize :: System.IO.FilePath -> IO FileSize
+findSize f	= do
+	fileExists	<- System.Directory.doesFileExist f
+
+	if fileExists
+		then System.IO.withFile f System.IO.ReadMode System.IO.hFileSize
+		else {-not a file-} Control.Exception.throwIO $ System.IO.Error.mkIOError System.IO.Error.illegalOperationErrorType ("file=" ++ show f ++ " either doesn't exist or has an unexpected type") Nothing (Just f)
+
+-- | Acquire statistics related to a list of file-sizes.
+getFileSizeStatistics
+	:: (Fractional mean, Floating standardDeviation)
+	=> [FileSize]
+	-> (Int, mean, standardDeviation)	-- ^ (The population-size, Mean size, Standard-deviation).
+getFileSizeStatistics fileSizes	= (
+	length fileSizes,
+	Factory.Math.Statistics.getMean fileSizes,
+	Factory.Math.Statistics.getStandardDeviation fileSizes
+ )
+
diff --git a/src-lib/FishFood/Data/Verbosity.hs b/src-lib/FishFood/Data/Verbosity.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/FishFood/Data/Verbosity.hs
@@ -0,0 +1,37 @@
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+{-
+	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@]	Instance-definitions for 'Distribution.Verbosity.Verbosity'.
+-}
+
+module FishFood.Data.Verbosity(
+-- * Constants
+	range
+) where
+
+import qualified	Distribution.Verbosity
+import qualified	ToolShed.Defaultable
+
+instance ToolShed.Defaultable.Defaultable Distribution.Verbosity.Verbosity	where
+	defaultValue	= Distribution.Verbosity.normal
+
+-- | The constant complete range of values.
+range :: [Distribution.Verbosity.Verbosity]
+range	= [minBound .. maxBound]
diff --git a/src-lib/FishFood/Profiler.hs b/src-lib/FishFood/Profiler.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/FishFood/Profiler.hs
@@ -0,0 +1,148 @@
+{-
+	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@]	Profiles lists of file-sizes.
+-}
+
+module FishFood.Profiler(
+-- * Types
+-- ** Type-synonyms
+--	Probability,
+--	Result,
+--	FileSizeDistribution,
+-- * Functions
+	calculateFileSizeDistribution,
+	formatFileSizeDistribution,
+-- ** Accessors
+	getFileSize,
+	getValue
+) where
+
+import			Control.Arrow((&&&),(***))
+import qualified	Control.Monad.Writer
+import qualified	Data.List
+import qualified	Data.Map
+import qualified	Data.Maybe
+import qualified	FishFood.Data.CommandOptions	as Data.CommandOptions
+import qualified	FishFood.Data.File		as Data.File
+import			FishFood.Data.Verbosity()
+import qualified	Text.Printf
+import qualified	ToolShed.Defaultable
+
+-- | Define a type to represent the fractional closed unit-interval.
+type Probability	= Double
+
+-- | Defines either the number of files or the probability that a files has a specific size.
+type Result	= (Data.File.FileSize, Either Int {-file-count-} Probability)
+
+-- | Accessor.
+getFileSize :: Result -> Data.File.FileSize
+getFileSize	= fst
+
+-- | Accessor.
+getValue :: Result -> Either Int {-file-count-} Probability
+getValue	= snd
+
+-- | Defines either a /Probability Mass Function/ or /Frequency-distribution/.
+type FileSizeDistribution	= [Result]
+
+-- | Calculates either the /Probability Mass Function/ or /Frequency-distribution/ for the specified files.
+calculateFileSizeDistribution :: (Floating ratio, RealFrac ratio) => Data.CommandOptions.CommandOptions ratio -> [Data.File.FileSize] -> Control.Monad.Writer.Writer [String] FileSizeDistribution
+calculateFileSizeDistribution commandOptions fileSizes	= let
+	binSizeDelta			= Data.CommandOptions.getBinSizeDelta commandOptions
+	deriveProbabilityMassFunction	= Data.CommandOptions.getDeriveProbabilityMassFunction commandOptions
+	nDecimalDigits			= Data.CommandOptions.getNDecimalDigits commandOptions
+
+	mean, standardDeviation :: Double
+	(nFiles, mean, standardDeviation)	= Data.File.getFileSizeStatistics fileSizes
+ in do
+	Control.Monad.Writer.tell [Text.Printf.printf "Files=%d, mean=%.*f, standard-deviation=%.*f" nFiles nDecimalDigits mean nDecimalDigits standardDeviation]
+
+	return {-to Writer-monad-} $ if standardDeviation == 0
+		then return {-to List-monad-} . (,) (head fileSizes) $ if deriveProbabilityMassFunction
+			then Right 1		-- i.e. certainty.
+			else Left nFiles	-- i.e. all.
+		else let
+			getDefaultedBinSizeIncrement :: Maybe Data.File.FileSize -> Data.File.FileSize
+			getDefaultedBinSizeIncrement	= Data.Maybe.fromMaybe $ round standardDeviation `max` 1 {-minimum increment-}	-- CAVEAT: guard against subsequent division by zero or infinite iteration.
+
+			calculatedBinSizes :: [Data.File.FileSize]
+			calculatedBinSizes	= map (
+				\fileSize	-> either (
+					div {-round down-} fileSize . getDefaultedBinSizeIncrement {-non-zero-}
+				) (
+					floor {-round down-} . (`logBase` fromIntegral fileSize)	-- CAVEAT: converts file-size 0, to bin-size -infinity.
+				) binSizeDelta
+			 ) fileSizes	-- Each bin spans the semi-closed integral interval [size, succ size), so round down fractional values to match the lower bin.
+
+			initialFrequencyDistribution :: Data.Map.Map Data.File.FileSize Int
+			initialFrequencyDistribution	= Data.Map.fromAscList . (
+				`zip` repeat 0	-- The initial file-count.
+			 ) . takeWhile (
+				<= maximum calculatedBinSizes
+			 ) . dropWhile (
+				< minimum calculatedBinSizes
+			 ) $ either (
+				\maybeBinSizeIncrement	-> iterate (+ getDefaultedBinSizeIncrement {-non-zero-} maybeBinSizeIncrement) 0
+			 ) (
+				\binRatio		-> map round {-file-sizes are integral-} $ iterate (* binRatio) 1	-- The sequence could be started at fractional values in the open unit-interval, but the only value less than 1 which may be required is 0 (which isn't a sequence-member), which will be created later on demand.
+			 ) binSizeDelta
+
+			mapBinSizeToFileSize :: Data.Map.Map Data.File.FileSize value -> Data.Map.Map Data.File.FileSize value
+			mapBinSizeToFileSize	= Data.Map.mapKeys $ \binSize -> either (
+				(* binSize) . getDefaultedBinSizeIncrement
+			 ) (
+				ceiling {-round up-} . (^^ binSize)	-- Converts binSize -infinity, back to file-size 0.
+			 ) binSizeDelta	-- Represent each bin by the minimum file-size it can accept.
+		in Data.Map.toList . (
+			if deriveProbabilityMassFunction
+				then Data.Map.map Right . mapBinSizeToFileSize . Data.Map.map ((/ fromIntegral nFiles {-non-zero-}) . fromIntegral)
+				else Data.Map.map Left . mapBinSizeToFileSize
+		) $ foldr (
+			Data.Map.insertWith (+) `flip` 1	-- Count the files allocated to each bin.
+		) initialFrequencyDistribution calculatedBinSizes
+
+-- | Formats a file-size distribution.
+formatFileSizeDistribution :: Data.CommandOptions.CommandOptions ratio -> FileSizeDistribution -> String
+formatFileSizeDistribution commandOptions	= Data.List.intercalate "\n" . map (
+	\(fileSize, value)	-> fileSize ++ " " ++ value
+ ) . (
+	if Data.CommandOptions.getVerbosity commandOptions > ToolShed.Defaultable.defaultValue
+		then (
+			[
+				(
+					($ (fileSizeWidth, fileSizeHeader)) &&& ($ (valueWidth, valueHeader))
+				) . uncurry $ Text.Printf.printf "%*s",	-- Column-headers.
+				(`replicate` '=') *** (`replicate` '=') $ columnWidths	-- Separator-bar.
+			] ++
+		) -- Section.
+		else id
+ ) . map (
+	Text.Printf.printf "%*d" fileSizeWidth *** either (
+		Text.Printf.printf "%*d" valueWidth
+	) (
+		Text.Printf.printf "%.*f" $ Data.CommandOptions.getNDecimalDigits commandOptions
+	)
+ ) where
+	fileSizeHeader, valueHeader :: String
+	headers@(fileSizeHeader, valueHeader)	= (,) "Bin-size" $ if Data.CommandOptions.getDeriveProbabilityMassFunction commandOptions then "Probability" else "Frequency"
+
+	fileSizeWidth, valueWidth :: Int
+	columnWidths@(fileSizeWidth, valueWidth)	= (`max` 10) . length *** length $ headers	-- CAVEAT: the data-length may exceed the header-length, so define a minimum.
+
diff --git a/src-test/FishFood/Test/Data/CommandOptions.hs b/src-test/FishFood/Test/Data/CommandOptions.hs
new file mode 100644
--- /dev/null
+++ b/src-test/FishFood/Test/Data/CommandOptions.hs
@@ -0,0 +1,65 @@
+{-# LANGUAGE CPP #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+{-
+	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@]	Implements 'Test.QuickCheck.Arbitrary' for 'Data.CommandOptions.CommandOptions'.
+-}
+
+module FishFood.Test.Data.CommandOptions(
+-- * Types
+-- ** Type-synonyms
+	CommandOptions
+) where
+
+import qualified	Test.QuickCheck
+import qualified	FishFood.Data.CommandOptions	as Data.CommandOptions
+import			FishFood.Test.Data.Verbosity()
+
+#if !MIN_VERSION_base(4,8,0)
+import	Control.Applicative((<$>), (<*>))
+#endif
+
+instance (
+	Enum				ratio,
+	Fractional			ratio,
+	Ord				ratio,
+	Show				ratio,
+	Test.QuickCheck.Arbitrary	ratio
+ ) => Test.QuickCheck.Arbitrary (Data.CommandOptions.CommandOptions ratio)	where
+	arbitrary	= do
+		deriveProbabilityMassFunction	<- Test.QuickCheck.arbitrary
+
+		Data.CommandOptions.mkCommandOptions <$> (
+			either (
+				Left . (succ . abs <$> {-into Maybe-monad-})
+			) (
+				Right . (+ recip 1000000) . succ . abs
+			) <$> Test.QuickCheck.arbitrary {-binSizeDelta-}
+		 ) <*> return {-to Gen-monad-} deriveProbabilityMassFunction <*> (
+			max (
+				if deriveProbabilityMassFunction then 1 else 0
+			) . (
+				`mod` 15 {-maximum permissible-}
+			) <$> Test.QuickCheck.arbitrary {-nDecimalDigits-}
+		 ) <*> Test.QuickCheck.arbitrary {-verbosity-}
+
+-- | Defines a concrete type for testing.
+type CommandOptions	= Data.CommandOptions.CommandOptions Double
+
diff --git a/src-test/FishFood/Test/Data/Verbosity.hs b/src-test/FishFood/Test/Data/Verbosity.hs
new file mode 100644
--- /dev/null
+++ b/src-test/FishFood/Test/Data/Verbosity.hs
@@ -0,0 +1,31 @@
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+{-
+	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@]	Implements 'Test.QuickCheck.Arbitrary' for 'Distribution.Verbosity.Verbosity'.
+-}
+
+module FishFood.Test.Data.Verbosity() where
+
+import qualified	Distribution.Verbosity
+import qualified	FishFood.Data.Verbosity	as Data.Verbosity
+import qualified	Test.QuickCheck
+
+instance Test.QuickCheck.Arbitrary Distribution.Verbosity.Verbosity	where
+	arbitrary	= Test.QuickCheck.elements Data.Verbosity.range
diff --git a/src-test/FishFood/Test/Profiler.hs b/src-test/FishFood/Test/Profiler.hs
new file mode 100644
--- /dev/null
+++ b/src-test/FishFood/Test/Profiler.hs
@@ -0,0 +1,58 @@
+{-
+	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 for 'Profiler'.
+-}
+
+module FishFood.Test.Profiler(
+-- * Constants
+	results
+) where
+
+import qualified	Control.Monad.Writer
+import qualified	Data.Either
+import qualified	Data.Set
+import qualified	FishFood.Data.CommandOptions		as Data.CommandOptions
+import qualified	FishFood.Data.File			as Data.File
+import qualified	FishFood.Profiler			as Profiler
+import qualified	FishFood.Test.Data.CommandOptions	as Test.Data.CommandOptions
+import qualified	Test.QuickCheck
+import			Test.QuickCheck((==>))
+import qualified	ToolShed.SelfValidate
+
+-- | The constant test-results for this data-type.
+results :: IO [Test.QuickCheck.Result]
+results	= mapM Test.QuickCheck.quickCheckResult [prop_calculateProbabilityMassFunction, prop_calculateFileSizeFrequencyDistribution, prop_attendance]	where
+	prop_calculateProbabilityMassFunction, prop_calculateFileSizeFrequencyDistribution, prop_attendance :: Test.Data.CommandOptions.CommandOptions -> [Data.File.FileSize] -> Test.QuickCheck.Property
+	prop_calculateProbabilityMassFunction commandOptions fileSizes	= not (null fileSizes) && ToolShed.SelfValidate.isValid commandOptions' ==> Test.QuickCheck.label "prop_calculateProbabilityMassFunction" . (<= recip 1000000) . (+ negate 1) . sum . Data.Either.rights {-probabilities-} . map Profiler.getValue . fst {-distribution-} . Control.Monad.Writer.runWriter . Profiler.calculateFileSizeDistribution commandOptions' $ map abs fileSizes	where
+		commandOptions'	= commandOptions { Data.CommandOptions.getDeriveProbabilityMassFunction	= True }
+
+	prop_calculateFileSizeFrequencyDistribution commandOptions fileSizes	= not (null fileSizes) && ToolShed.SelfValidate.isValid commandOptions' ==> Test.QuickCheck.label "prop_calculateFileSizeFrequencyDistribution" . (== length fileSizes) . sum . Data.Either.lefts {-frequency-} . map Profiler.getValue . fst {-distribution-} . Control.Monad.Writer.runWriter . Profiler.calculateFileSizeDistribution commandOptions' $ map abs fileSizes	where
+		commandOptions'	= commandOptions { Data.CommandOptions.getDeriveProbabilityMassFunction	= False }
+
+	prop_attendance commandOptions fileSizes	= not (null fileSizes') && ToolShed.SelfValidate.isValid commandOptions' ==> Test.QuickCheck.label "prop_attendance" . (
+		== Data.Set.fromList fileSizes'
+	 ) . Data.Set.fromList . map Profiler.getFileSize . filter (
+		(/= 0) . either fromIntegral id . Profiler.getValue	-- Remove file-sizes which match zero actual files.
+	 ) . fst {-distribution-} . Control.Monad.Writer.runWriter $ Profiler.calculateFileSizeDistribution commandOptions' fileSizes'	where
+		fileSizes'	= map abs fileSizes
+
+		commandOptions' :: Test.Data.CommandOptions.CommandOptions
+		commandOptions'	= Data.CommandOptions.setBinSizeIncrement 1 commandOptions
+
diff --git a/src-test/Main.hs b/src-test/Main.hs
new file mode 100644
--- /dev/null
+++ b/src-test/Main.hs
@@ -0,0 +1,44 @@
+{-
+	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@]
+
+	* The entry-point to the application's test-suite.
+-}
+
+module Main(main) where
+
+import			Control.Arrow((***))
+import qualified	Control.Monad
+import qualified	FishFood.Test.Profiler	as Test.Profiler
+import qualified	System.Exit
+import qualified	ToolShed.Test.QuickCheck.Result
+
+-- | Entry-point.
+main :: IO ()
+main	= mapM_ (
+	snd {-exit-status-} . (
+		putStrLn . (++ ":") *** (
+			>>= (`Control.Monad.unless` System.Exit.exitFailure) . all ToolShed.Test.QuickCheck.Result.isSuccessful
+		)
+	)
+ ) [
+	("Profiler",	Test.Profiler.results)
+ ]
+
diff --git a/src/FishFood/Data/CommandOptions.hs b/src/FishFood/Data/CommandOptions.hs
deleted file mode 100644
--- a/src/FishFood/Data/CommandOptions.hs
+++ /dev/null
@@ -1,113 +0,0 @@
-{-
-	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 options for program-operation.
-
-	* Defines an appropriate default value, which is expected to be over-ridden on the command-line.
-
-	* Self-validates.
--}
-
-module FishFood.Data.CommandOptions(
--- * Types
--- ** Type-synonyms
-	BinSizeDelta,
--- ** Data-types
-	CommandOptions(
---		MkCommandOptions,
-		getBinSizeDelta,
-		getDeriveProbabilityMassFunction,
-		getNDecimalDigits,
-		getVerbosity
-	),
--- * Functions
--- ** Constructors
-	mkCommandOptions,
--- ** Mutators
-	setBinSizeIncrement,
-	setBinSizeRatio
-) where
-
-import qualified	Data.Maybe
-import qualified	Distribution.Verbosity
-import qualified	FishFood.Data.File	as Data.File
-import qualified	ToolShed.Defaultable
-import qualified	ToolShed.SelfValidate
-
--- | Either an arithmetic size-increase for which there's a default, or a geometric size-ratio.
-type BinSizeDelta ratio	= Either (Maybe Data.File.FileSize) ratio
-
--- | Declares a record to contain command-line options.
-data CommandOptions ratio	= MkCommandOptions {
-	getBinSizeDelta				:: BinSizeDelta ratio,			-- ^ Either the arithmetic size-increase (defaulting to one standard-deviation), or the geometric size-ratio, of the sequence of bins into which files are categorized.
-	getDeriveProbabilityMassFunction	:: Bool,				-- ^ Whether to derive the "Probability mass function" rather than the "Frequency-distribution".
-	getNDecimalDigits			:: Int,					-- ^ The precision to which fractional data is displayed.
-	getVerbosity				:: Distribution.Verbosity.Verbosity	-- ^ The threshold for ancillary information-output.
-} deriving Show
-
-instance ToolShed.Defaultable.Defaultable (CommandOptions ratio)	where
-	defaultValue	= MkCommandOptions {
-		getBinSizeDelta				= Left Nothing,	-- Interpreted as one standard-deviation.
-		getDeriveProbabilityMassFunction	= False,
-		getNDecimalDigits			= 3,
-		getVerbosity				= Distribution.Verbosity.normal
-	}
-
-instance (Num ratio, Ord ratio, Show ratio) => ToolShed.SelfValidate.SelfValidator (CommandOptions ratio)	where
-	getErrors commandOptions@MkCommandOptions {
-		getBinSizeDelta				= binSizeDelta,
-		getDeriveProbabilityMassFunction	= deriveProbabilityMassFunction,
-		getNDecimalDigits			= nDecimalDigits
-	} = map snd $ filter fst [
-		(
-			either (Data.Maybe.maybe False (<= 0)) (<= 1) binSizeDelta,
-			"either the bin-size's arithmetic increase must exceed zero, or it's geometric ratio must exceed one; " ++ show commandOptions ++ "."
-		), (
-			deriveProbabilityMassFunction && nDecimalDigits < 1,
-			"the number of decimal digits must exceed zero to adequately represent probabilities; " ++ show commandOptions ++ "."
-		),
-		let
-			maxNDecimalDigits	= floor $ fromIntegral (
-				floatDigits (
-					undefined :: Double	-- CAVEAT: the actual type could be merely 'Float', but that's currently unknown.
-				)
-			 ) * (logBase 10 2 :: Double)
-		in (
-			nDecimalDigits > maxNDecimalDigits,
-			"the number of decimal digits shouldn't exceed " ++ show maxNDecimalDigits ++ "; " ++ show commandOptions ++ "."
-		)
-	 ]
-
--- | Smart constructor.
-mkCommandOptions :: (Num ratio, Ord ratio, Show ratio) => BinSizeDelta ratio -> Bool -> Int -> Distribution.Verbosity.Verbosity -> CommandOptions ratio
-mkCommandOptions binSizeDelta deriveProbabilityMassFunction nDecimalDigits verbosity
-	| ToolShed.SelfValidate.isValid commandOptions	= commandOptions
-	| otherwise					= error $ "FishFood.Data.CommandOptions.mkCommandOptions:\t" ++ ToolShed.SelfValidate.getFirstError commandOptions
-	where
-		commandOptions	= MkCommandOptions binSizeDelta deriveProbabilityMassFunction nDecimalDigits verbosity
-
--- | Mutator.
-setBinSizeIncrement :: Data.File.FileSize -> CommandOptions ratio -> CommandOptions ratio
-setBinSizeIncrement fileSize commandOptions	= commandOptions { getBinSizeDelta = Left $ Just fileSize }
-
--- | Mutator.
-setBinSizeRatio :: ratio -> CommandOptions ratio -> CommandOptions ratio
-setBinSizeRatio ratio commandOptions	= commandOptions { getBinSizeDelta = Right ratio }
diff --git a/src/FishFood/Data/File.hs b/src/FishFood/Data/File.hs
deleted file mode 100644
--- a/src/FishFood/Data/File.hs
+++ /dev/null
@@ -1,60 +0,0 @@
-{-
-	Copyright (C) 2013-2014 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@]	Allows one to find the size of a file, & to gather statistics on a population.
--}
-
-module FishFood.Data.File(
--- * Types
--- ** Type-synonyms
-	FileSize,
--- * Functions
-	findSize,
-	getFileSizeStatistics
-) where
-
-import qualified	Control.Exception
-import qualified	Factory.Math.Statistics
-import qualified	System.Directory
-import qualified	System.IO
-import qualified	System.IO.Error
-
--- | A type-synonym specifically to hold file-sizes (in bytes).
-type FileSize	= Integer	-- Matches the return-type of 'IO.hFileSize'.
-
--- | Get the size of the specified file.
-findSize :: System.IO.FilePath -> IO FileSize
-findSize f	= do
-	fileExists	<- System.Directory.doesFileExist f
-
-	if fileExists
-		then System.IO.withFile f System.IO.ReadMode System.IO.hFileSize
-		else {-not a file-} Control.Exception.throwIO $ System.IO.Error.mkIOError System.IO.Error.illegalOperationErrorType ("file=" ++ show f ++ " either doesn't exist or has an unexpected type") Nothing (Just f)
-
--- | Acquire statistics related to a list of file-sizes.
-getFileSizeStatistics
-	:: (Fractional mean, Floating standardDeviation)
-	=> [FileSize]
-	-> (Int, mean, standardDeviation)	-- ^ (The population-size, Mean size, Standard-deviation).
-getFileSizeStatistics fileSizes	= (
-	length fileSizes,
-	Factory.Math.Statistics.getMean fileSizes,
-	Factory.Math.Statistics.getStandardDeviation fileSizes
- )
-
diff --git a/src/FishFood/Data/Verbosity.hs b/src/FishFood/Data/Verbosity.hs
deleted file mode 100644
--- a/src/FishFood/Data/Verbosity.hs
+++ /dev/null
@@ -1,37 +0,0 @@
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-{-
-	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@]	Instance-definitions for 'Distribution.Verbosity.Verbosity'.
--}
-
-module FishFood.Data.Verbosity(
--- * Constants
-	range
-) where
-
-import qualified	Distribution.Verbosity
-import qualified	ToolShed.Defaultable
-
-instance ToolShed.Defaultable.Defaultable Distribution.Verbosity.Verbosity	where
-	defaultValue	= Distribution.Verbosity.normal
-
--- | The constant complete range of values.
-range :: [Distribution.Verbosity.Verbosity]
-range	= [minBound .. maxBound]
diff --git a/src/FishFood/Profiler.hs b/src/FishFood/Profiler.hs
deleted file mode 100644
--- a/src/FishFood/Profiler.hs
+++ /dev/null
@@ -1,148 +0,0 @@
-{-
-	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@]	Profiles lists of file-sizes.
--}
-
-module FishFood.Profiler(
--- * Types
--- ** Type-synonyms
---	Probability,
---	Result,
---	FileSizeDistribution,
--- * Functions
-	calculateFileSizeDistribution,
-	formatFileSizeDistribution,
--- ** Accessors
-	getFileSize,
-	getValue
-) where
-
-import			Control.Arrow((&&&),(***))
-import qualified	Control.Monad.Writer
-import qualified	Data.List
-import qualified	Data.Map
-import qualified	Data.Maybe
-import qualified	FishFood.Data.CommandOptions	as Data.CommandOptions
-import qualified	FishFood.Data.File		as Data.File
-import			FishFood.Data.Verbosity()
-import qualified	Text.Printf
-import qualified	ToolShed.Defaultable
-
--- | Define a type to represent the fractional closed unit-interval.
-type Probability	= Double
-
--- | Defines either the number of files or the probability that a files has a specific size.
-type Result	= (Data.File.FileSize, Either Int {-file-count-} Probability)
-
--- | Accessor.
-getFileSize :: Result -> Data.File.FileSize
-getFileSize	= fst
-
--- | Accessor.
-getValue :: Result -> Either Int {-file-count-} Probability
-getValue	= snd
-
--- | Defines either a /Probability Mass Function/ or /Frequency-distribution/.
-type FileSizeDistribution	= [Result]
-
--- | Calculates either the /Probability Mass Function/ or /Frequency-distribution/ for the specified files.
-calculateFileSizeDistribution :: (Floating ratio, RealFrac ratio) => Data.CommandOptions.CommandOptions ratio -> [Data.File.FileSize] -> Control.Monad.Writer.Writer [String] FileSizeDistribution
-calculateFileSizeDistribution commandOptions fileSizes	= let
-	binSizeDelta			= Data.CommandOptions.getBinSizeDelta commandOptions
-	deriveProbabilityMassFunction	= Data.CommandOptions.getDeriveProbabilityMassFunction commandOptions
-	nDecimalDigits			= Data.CommandOptions.getNDecimalDigits commandOptions
-
-	mean, standardDeviation :: Double
-	(nFiles, mean, standardDeviation)	= Data.File.getFileSizeStatistics fileSizes
- in do
-	Control.Monad.Writer.tell [Text.Printf.printf "Files=%d, mean=%.*f, standard-deviation=%.*f" nFiles nDecimalDigits mean nDecimalDigits standardDeviation]
-
-	return {-to Writer-monad-} $ if standardDeviation == 0
-		then return {-to List-monad-} . (,) (head fileSizes) $ if deriveProbabilityMassFunction
-			then Right 1		-- i.e. certainty.
-			else Left nFiles	-- i.e. all.
-		else let
-			getDefaultedBinSizeIncrement :: Maybe Data.File.FileSize -> Data.File.FileSize
-			getDefaultedBinSizeIncrement	= Data.Maybe.fromMaybe $ round standardDeviation `max` 1 {-minimum increment-}	-- CAVEAT: guard against subsequent division by zero or infinite iteration.
-
-			calculatedBinSizes :: [Data.File.FileSize]
-			calculatedBinSizes	= map (
-				\fileSize	-> either (
-					div {-round down-} fileSize . getDefaultedBinSizeIncrement {-non-zero-}
-				) (
-					floor {-round down-} . (`logBase` fromIntegral fileSize)	-- CAVEAT: converts file-size 0, to bin-size -infinity.
-				) binSizeDelta
-			 ) fileSizes	-- Each bin spans the semi-closed integral interval [size, succ size), so round down fractional values to match the lower bin.
-
-			initialFrequencyDistribution :: Data.Map.Map Data.File.FileSize Int
-			initialFrequencyDistribution	= Data.Map.fromAscList . (
-				`zip` repeat 0	-- The initial file-count.
-			 ) . takeWhile (
-				<= maximum calculatedBinSizes
-			 ) . dropWhile (
-				< minimum calculatedBinSizes
-			 ) $ either (
-				\maybeBinSizeIncrement	-> iterate (+ getDefaultedBinSizeIncrement {-non-zero-} maybeBinSizeIncrement) 0
-			 ) (
-				\binRatio		-> map round {-file-sizes are integral-} $ iterate (* binRatio) 1	-- The sequence could be started at fractional values in the open unit-interval, but the only value less than 1 which may be required is 0 (which isn't a sequence-member), which will be created later on demand.
-			 ) binSizeDelta
-
-			mapBinSizeToFileSize :: Data.Map.Map Data.File.FileSize value -> Data.Map.Map Data.File.FileSize value
-			mapBinSizeToFileSize	= Data.Map.mapKeys $ \binSize -> either (
-				(* binSize) . getDefaultedBinSizeIncrement
-			 ) (
-				ceiling {-round up-} . (^^ binSize)	-- Converts binSize -infinity, back to file-size 0.
-			 ) binSizeDelta	-- Represent each bin by the minimum file-size it can accept.
-		in Data.Map.toList . (
-			if deriveProbabilityMassFunction
-				then Data.Map.map Right . mapBinSizeToFileSize . Data.Map.map ((/ fromIntegral nFiles {-non-zero-}) . fromIntegral)
-				else Data.Map.map Left . mapBinSizeToFileSize
-		) $ foldr (
-			Data.Map.insertWith (+) `flip` 1	-- Count the files allocated to each bin.
-		) initialFrequencyDistribution calculatedBinSizes
-
--- | Formats a file-size distribution.
-formatFileSizeDistribution :: Data.CommandOptions.CommandOptions ratio -> FileSizeDistribution -> String
-formatFileSizeDistribution commandOptions	= Data.List.intercalate "\n" . map (
-	\(fileSize, value)	-> fileSize ++ " " ++ value
- ) . (
-	if Data.CommandOptions.getVerbosity commandOptions > ToolShed.Defaultable.defaultValue
-		then (
-			[
-				(
-					($ (fileSizeWidth, fileSizeHeader)) &&& ($ (valueWidth, valueHeader))
-				) . uncurry $ Text.Printf.printf "%*s",	-- Column-headers.
-				(`replicate` '=') *** (`replicate` '=') $ columnWidths	-- Separator-bar.
-			] ++
-		) -- Section.
-		else id
- ) . map (
-	Text.Printf.printf "%*d" fileSizeWidth *** either (
-		Text.Printf.printf "%*d" valueWidth
-	) (
-		Text.Printf.printf "%.*f" $ Data.CommandOptions.getNDecimalDigits commandOptions
-	)
- ) where
-	fileSizeHeader, valueHeader :: String
-	headers@(fileSizeHeader, valueHeader)	= (,) "Bin-size" $ if Data.CommandOptions.getDeriveProbabilityMassFunction commandOptions then "Probability" else "Frequency"
-
-	fileSizeWidth, valueWidth :: Int
-	columnWidths@(fileSizeWidth, valueWidth)	= (`max` 10) . length *** length $ headers	-- CAVEAT: the data-length may exceed the header-length, so define a minimum.
-
diff --git a/src/FishFood/Test/Data/CommandOptions.hs b/src/FishFood/Test/Data/CommandOptions.hs
deleted file mode 100644
--- a/src/FishFood/Test/Data/CommandOptions.hs
+++ /dev/null
@@ -1,62 +0,0 @@
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-{-
-	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@]	Implements 'Test.QuickCheck.Arbitrary' for 'Data.CommandOptions.CommandOptions'.
--}
-
-module FishFood.Test.Data.CommandOptions(
--- * Types
--- ** Type-synonyms
-	CommandOptions
-) where
-
-import Prelude hiding ((<$>), (<*>))	-- The "Prelude" from 'base-4.8' exports this symbol.
-import			Control.Applicative((<$>), (<*>))
-import qualified	Test.QuickCheck
-import qualified	FishFood.Data.CommandOptions	as Data.CommandOptions
-import			FishFood.Test.Data.Verbosity()
-
-instance (
-	Enum				ratio,
-	Fractional			ratio,
-	Ord				ratio,
-	Show				ratio,
-	Test.QuickCheck.Arbitrary	ratio
- ) => Test.QuickCheck.Arbitrary (Data.CommandOptions.CommandOptions ratio)	where
-	arbitrary	= do
-		deriveProbabilityMassFunction	<- Test.QuickCheck.arbitrary
-
-		Data.CommandOptions.mkCommandOptions <$> (
-			either (
-				Left . (succ . abs <$> {-into Maybe-monad-})
-			) (
-				Right . (+ recip 1000000) . succ . abs
-			) <$> Test.QuickCheck.arbitrary {-binSizeDelta-}
-		 ) <*> return {-to Gen-monad-} deriveProbabilityMassFunction <*> (
-			max (
-				if deriveProbabilityMassFunction then 1 else 0
-			) . (
-				`mod` 15 {-maximum permissible-}
-			) <$> Test.QuickCheck.arbitrary {-nDecimalDigits-}
-		 ) <*> Test.QuickCheck.arbitrary {-verbosity-}
-
--- | Defines a concrete type for testing.
-type CommandOptions	= Data.CommandOptions.CommandOptions Double
-
diff --git a/src/FishFood/Test/Data/Verbosity.hs b/src/FishFood/Test/Data/Verbosity.hs
deleted file mode 100644
--- a/src/FishFood/Test/Data/Verbosity.hs
+++ /dev/null
@@ -1,31 +0,0 @@
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-{-
-	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@]	Implements 'Test.QuickCheck.Arbitrary' for 'Distribution.Verbosity.Verbosity'.
--}
-
-module FishFood.Test.Data.Verbosity() where
-
-import qualified	Distribution.Verbosity
-import qualified	FishFood.Data.Verbosity	as Data.Verbosity
-import qualified	Test.QuickCheck
-
-instance Test.QuickCheck.Arbitrary Distribution.Verbosity.Verbosity	where
-	arbitrary	= Test.QuickCheck.elements Data.Verbosity.range
diff --git a/src/FishFood/Test/Profiler.hs b/src/FishFood/Test/Profiler.hs
deleted file mode 100644
--- a/src/FishFood/Test/Profiler.hs
+++ /dev/null
@@ -1,58 +0,0 @@
-{-
-	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@]	Implements 'Test.QuickCheck.Arbitrary' & defines /QuickCheck/-properties for 'Profiler'.
--}
-
-module FishFood.Test.Profiler(
--- * Functions
-	quickChecks
-) where
-
-import qualified	Control.Monad.Writer
-import qualified	Data.Either
-import qualified	Data.Set
-import qualified	FishFood.Data.CommandOptions		as Data.CommandOptions
-import qualified	FishFood.Data.File			as Data.File
-import qualified	FishFood.Profiler			as Profiler
-import qualified	FishFood.Test.Data.CommandOptions	as Test.Data.CommandOptions
-import qualified	Test.QuickCheck
-import			Test.QuickCheck((==>))
-import qualified	ToolShed.SelfValidate
-
--- | Defines invariant properties.
-quickChecks :: IO ()
-quickChecks	= Test.QuickCheck.quickCheck `mapM_` [prop_calculateProbabilityMassFunction, prop_calculateFileSizeFrequencyDistribution, prop_attendance]	where
-	prop_calculateProbabilityMassFunction, prop_calculateFileSizeFrequencyDistribution, prop_attendance :: Test.Data.CommandOptions.CommandOptions -> [Data.File.FileSize] -> Test.QuickCheck.Property
-	prop_calculateProbabilityMassFunction commandOptions fileSizes	= not (null fileSizes) && ToolShed.SelfValidate.isValid commandOptions' ==> Test.QuickCheck.label "prop_calculateProbabilityMassFunction" . (<= recip 1000000) . (+ negate 1) . sum . Data.Either.rights {-probabilities-} . map Profiler.getValue . fst {-distribution-} . Control.Monad.Writer.runWriter . Profiler.calculateFileSizeDistribution commandOptions' $ map abs fileSizes	where
-		commandOptions'	= commandOptions { Data.CommandOptions.getDeriveProbabilityMassFunction	= True }
-
-	prop_calculateFileSizeFrequencyDistribution commandOptions fileSizes	= not (null fileSizes) && ToolShed.SelfValidate.isValid commandOptions' ==> Test.QuickCheck.label "prop_calculateFileSizeFrequencyDistribution" . (== length fileSizes) . sum . Data.Either.lefts {-frequency-} . map Profiler.getValue . fst {-distribution-} . Control.Monad.Writer.runWriter . Profiler.calculateFileSizeDistribution commandOptions' $ map abs fileSizes	where
-		commandOptions'	= commandOptions { Data.CommandOptions.getDeriveProbabilityMassFunction	= False }
-
-	prop_attendance commandOptions fileSizes	= not (null fileSizes') && ToolShed.SelfValidate.isValid commandOptions' ==> Test.QuickCheck.label "prop_attendance" . (
-		== Data.Set.fromList fileSizes'
-	 ) . Data.Set.fromList . map Profiler.getFileSize . filter (
-		(/= 0) . either fromIntegral id . Profiler.getValue	-- Remove file-sizes which match zero actual files.
-	 ) . fst {-distribution-} . Control.Monad.Writer.runWriter $ Profiler.calculateFileSizeDistribution commandOptions' fileSizes'	where
-		fileSizes'	= map abs fileSizes
-
-		commandOptions' :: Test.Data.CommandOptions.CommandOptions
-		commandOptions'	= Data.CommandOptions.setBinSizeIncrement 1 commandOptions
-
diff --git a/src/FishFood/Test/QuickChecks.hs b/src/FishFood/Test/QuickChecks.hs
deleted file mode 100644
--- a/src/FishFood/Test/QuickChecks.hs
+++ /dev/null
@@ -1,38 +0,0 @@
-{-
-	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@]	Calls the /quickChecks/-functions for modules supporting this feature.
--}
-
-module FishFood.Test.QuickChecks(
--- * Functions
-	run
-) where
-
-import qualified	Control.Arrow
-import qualified	FishFood.Test.Profiler	as Test.Profiler
-
--- | Runs checks on invariant properties.
-run :: IO ()
-run	= mapM_ (
-	uncurry (>>) . Control.Arrow.first putStrLn
- ) [
-	("Profiler",	Test.Profiler.quickChecks)
- ]
-
diff --git a/src/Main.hs b/src/Main.hs
deleted file mode 100644
--- a/src/Main.hs
+++ /dev/null
@@ -1,181 +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@]
-
-	* Contains the entry-point of the application.
-
-	* Processes the command-line arguments.
-
-	* Delegates the task to "Profiler".
--}
-
-module Main(main) where
-
-import Prelude hiding ((<$>), (<*>))	-- The "Prelude" from 'base-4.8' exports this symbol.
-import			Control.Applicative((<$>),(<*>))
-import qualified	Control.Monad
-import qualified	Control.Monad.Writer
-import qualified	Data.List
-import qualified	Data.Maybe
-import qualified	Data.Version
-import qualified	Distribution.Package
-import qualified	Distribution.Text
-import qualified	Distribution.Version
-import qualified	FishFood.Data.CommandOptions	as Data.CommandOptions
-import qualified	FishFood.Data.File		as Data.File
-import qualified	FishFood.Data.Verbosity		as Data.Verbosity
-import qualified	FishFood.Profiler		as Profiler
-import qualified	FishFood.Test.QuickChecks	as Test.QuickChecks
-import qualified	Paths_fishfood			as Paths	-- Either local stub, or package-instance autogenerated by 'Setup.hs build'.
-import qualified	System.Console.GetOpt		as G
-import qualified	System.Environment
-import qualified	System.Exit
-import qualified	System.Info
-import qualified	System.IO
-import qualified	System.IO.Error
-import qualified	ToolShed.Data.List
-import qualified	ToolShed.Defaultable
-import qualified	ToolShed.SelfValidate
-
--- | Define the concrete type of command-options.
-type CommandOptions	= Data.CommandOptions.CommandOptions Double
-
--- | Used to thread user-defined command-line options, though the list of functions which implement them.
-type CommandLineAction	= CommandOptions -> IO CommandOptions	-- Supplied as the type-argument to 'G.OptDescr'.
-
--- | On failure to parse the specified string, returns an explanatory error.
-read' :: Read a => String -> String -> a
-read' errorMessage s	= case reads s of
-	[(x, "")]	-> x
-	_		-> error $ errorMessage ++ show s
-
--- | On failure to parse a command-line argument, returns an explanatory error.
-readCommandArg :: Read a => String -> a
-readCommandArg	= read' "failed to parse command-line argument "
-
--- | Reads a bounded integral from the command-line, guarding against overflow.
-readBoundedIntegral :: Integral i => String -> i
-readBoundedIntegral s
-	| fromIntegral bounded /= unbounded	= error $ "integral value exceeds permissible bounds; " ++ show unbounded ++ "."
-	| otherwise				= bounded
-	where
-		unbounded	= readCommandArg s
-		bounded		= fromInteger unbounded
-
-{- |
-	* Parses the command-line options, which over-ride default values.
-
-	* Any arguments which follow known options, are interpreted as file-names.
-
-	* If the specified file-name is /-/, then the actual file-names are read from /standard-input/, to augment any other non-options specified.
--}
-main :: IO ()
-main	= do
-	progName	<- System.Environment.getProgName
-
-	let
-		defaultCommandOptions :: CommandOptions
-		defaultCommandOptions	= ToolShed.Defaultable.defaultValue
-
-		optDescrList :: [G.OptDescr CommandLineAction]
-		optDescrList	= [
---				 String	[String]				(G.ArgDescr CommandLineAction)				String
-			G.Option "?"	["help"]				(G.NoArg $ const printUsage)				"Display this help, & then exit.",
-			G.Option ""	["verbosity"]				(
-				setVerbosity `G.ReqArg` ToolShed.Data.List.showListWith listDelimiters Data.Verbosity.range ""
-
-			)														("Define the log-level; default '" ++ show (Data.CommandOptions.getVerbosity defaultCommandOptions) ++ "'."
-			),
-			G.Option "v"	["version"]				(G.NoArg $ const printVersion)				"Print version-information, & then exit.",
-			G.Option "s"	["binSizeIncrement"]			(setBinSizeIncrement `G.ReqArg` "<Int>")		"The constant size-increase in the arithmetic sequence of bins into which the byte-sizes of files are categorised; defaulting to one standard-deviation.",
-			G.Option "r"	["binSizeRatio"]			(setBinSizeRatio `G.ReqArg` "<Float>")			"The constant size-ratio in the geometric sequence of bins into which the byte-sizes of files are categorised; an alternative to 'binSizeIncrement'.",
-			G.Option "p"	["deriveProbabilityMassFunction"]	(setDeriveProbabilityMassFunction `G.OptArg` "<Bool>")	("Whether to derive the \"Probability mass function\" rather than the \"Frequency-distribution\"; default '" ++ show (Data.CommandOptions.getDeriveProbabilityMassFunction defaultCommandOptions) ++ "'."),
-			G.Option "d"	["nDecimalDigits"]			(setNDecimalDigits `G.ReqArg` "<Int>")			("The precision to which fractional auxiliary data is displayed; default " ++ show (Data.CommandOptions.getNDecimalDigits defaultCommandOptions) ++ "."),
-			G.Option "q"	["runQuickChecks"]			(G.NoArg runQuickChecks)				"Test the implementation, by validating some invariant properties using arbitrary data; & then exit."
-		 ] where
-			listDelimiters	= ('(', '|', ')')
-
-			setBinSizeIncrement, setBinSizeRatio, setNDecimalDigits, setVerbosity :: String -> CommandLineAction
-			setBinSizeIncrement arg			= return {-to IO-monad-} . Data.CommandOptions.setBinSizeIncrement (readCommandArg arg)
-			setBinSizeRatio arg			= return {-to IO-monad-} . Data.CommandOptions.setBinSizeRatio (readCommandArg arg)
-			setNDecimalDigits arg commandOptions	= return {-to IO-monad-} commandOptions { Data.CommandOptions.getNDecimalDigits = readBoundedIntegral arg }
-			setVerbosity arg commandOptions		= return {-to IO-monad-} commandOptions { Data.CommandOptions.getVerbosity = readCommandArg arg }
-
-			setDeriveProbabilityMassFunction :: Maybe String -> CommandLineAction
-			setDeriveProbabilityMassFunction arg commandOptions	= return {-to IO-monad-} commandOptions { Data.CommandOptions.getDeriveProbabilityMassFunction = Data.Maybe.maybe True readCommandArg arg }
-
-			printVersion, printUsage :: IO CommandOptions
-			printVersion	= System.IO.hPutStrLn System.IO.stderr (
-				Distribution.Text.display packageIdentifier ++ "\n\nCompiled by " ++ show compiler ++ ".\n\nCopyright (C) 2013-2015 " ++ 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.
-					Distribution.Package.pkgVersion	= Distribution.Version.Version (Data.Version.versionBranch Paths.version) []
-				}
-
-				author, compiler :: String
-				author		= "Dr. Alistair Ward"
-				compiler	= System.Info.compilerName ++ "-" ++ Data.List.intercalate "." (map show $ Data.Version.versionBranch System.Info.compilerVersion)
-
-			printUsage	= System.IO.hPutStrLn System.IO.stderr ("Usage:\t" ++ G.usageInfo progName optDescrList ++ "  [<File-path> ...]") >> System.Exit.exitWith System.Exit.ExitSuccess
-
-			runQuickChecks :: CommandOptions -> IO CommandOptions
-			runQuickChecks _	= Test.QuickChecks.run >> System.Exit.exitWith System.Exit.ExitSuccess
-
-	args	<- System.Environment.getArgs
-
-	case G.getOpt G.RequireOrder optDescrList args of
-		(commandLineActions, nonOptions, [{-errors-}])	-> do
-			commandOptions	<- Data.List.foldl' (>>=) (return {-to IO-monad-} ToolShed.Defaultable.defaultValue) commandLineActions
-
-			if not $ ToolShed.SelfValidate.isValid commandOptions
-				then fail $ ToolShed.SelfValidate.getFirstError commandOptions
-				else if null nonOptions
-					then fail "zero file-paths specified"
-					else let
-						standardInputProxy	= "-"
-					in do
-						filePaths	<- if standardInputProxy `elem` nonOptions
-							then let
-								getFilePaths :: IO [String]
-								getFilePaths	= do
-									eof	<- System.IO.isEOF
-
-									if eof
-										then return {-to IO-monad-} []
-										else {-more to read-} (:) <$> getLine <*> getFilePaths {-recurse-}
-							in do
-								filePaths	<- (filter (/= standardInputProxy) nonOptions ++) <$> getFilePaths
-
-								if null filePaths
-									then fail "zero file-paths"
-									else return filePaths
-							else {-real fileNames-} return {-to IO-monad-} nonOptions
-
-						Control.Monad.when (Data.CommandOptions.getVerbosity commandOptions == maxBound) $ System.IO.hPrint System.IO.stderr filePaths	-- CAVEAT: potentially very long.
-
-						(fileSizeDistribution, statistics)	<- Control.Monad.Writer.runWriter . Profiler.calculateFileSizeDistribution commandOptions <$> mapM Data.File.findSize (Data.List.nub filePaths)
-
-						Control.Monad.when (Data.CommandOptions.getVerbosity commandOptions > ToolShed.Defaultable.defaultValue) $ mapM_ (System.IO.hPutStrLn System.IO.stderr) statistics
-
-						System.IO.putStrLn $ Profiler.formatFileSizeDistribution commandOptions fileSizeDistribution
-		(_, _, errors)	-> System.IO.Error.ioError . System.IO.Error.userError $ concatMap init {-chop-} errors
-
