diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2016 Tom Nielsen
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/datafiles/iris.data b/datafiles/iris.data
new file mode 100644
--- /dev/null
+++ b/datafiles/iris.data
@@ -0,0 +1,151 @@
+5.1,3.5,1.4,0.2,Iris-setosa
+4.9,3.0,1.4,0.2,Iris-setosa
+4.7,3.2,1.3,0.2,Iris-setosa
+4.6,3.1,1.5,0.2,Iris-setosa
+5.0,3.6,1.4,0.2,Iris-setosa
+5.4,3.9,1.7,0.4,Iris-setosa
+4.6,3.4,1.4,0.3,Iris-setosa
+5.0,3.4,1.5,0.2,Iris-setosa
+4.4,2.9,1.4,0.2,Iris-setosa
+4.9,3.1,1.5,0.1,Iris-setosa
+5.4,3.7,1.5,0.2,Iris-setosa
+4.8,3.4,1.6,0.2,Iris-setosa
+4.8,3.0,1.4,0.1,Iris-setosa
+4.3,3.0,1.1,0.1,Iris-setosa
+5.8,4.0,1.2,0.2,Iris-setosa
+5.7,4.4,1.5,0.4,Iris-setosa
+5.4,3.9,1.3,0.4,Iris-setosa
+5.1,3.5,1.4,0.3,Iris-setosa
+5.7,3.8,1.7,0.3,Iris-setosa
+5.1,3.8,1.5,0.3,Iris-setosa
+5.4,3.4,1.7,0.2,Iris-setosa
+5.1,3.7,1.5,0.4,Iris-setosa
+4.6,3.6,1.0,0.2,Iris-setosa
+5.1,3.3,1.7,0.5,Iris-setosa
+4.8,3.4,1.9,0.2,Iris-setosa
+5.0,3.0,1.6,0.2,Iris-setosa
+5.0,3.4,1.6,0.4,Iris-setosa
+5.2,3.5,1.5,0.2,Iris-setosa
+5.2,3.4,1.4,0.2,Iris-setosa
+4.7,3.2,1.6,0.2,Iris-setosa
+4.8,3.1,1.6,0.2,Iris-setosa
+5.4,3.4,1.5,0.4,Iris-setosa
+5.2,4.1,1.5,0.1,Iris-setosa
+5.5,4.2,1.4,0.2,Iris-setosa
+4.9,3.1,1.5,0.1,Iris-setosa
+5.0,3.2,1.2,0.2,Iris-setosa
+5.5,3.5,1.3,0.2,Iris-setosa
+4.9,3.1,1.5,0.1,Iris-setosa
+4.4,3.0,1.3,0.2,Iris-setosa
+5.1,3.4,1.5,0.2,Iris-setosa
+5.0,3.5,1.3,0.3,Iris-setosa
+4.5,2.3,1.3,0.3,Iris-setosa
+4.4,3.2,1.3,0.2,Iris-setosa
+5.0,3.5,1.6,0.6,Iris-setosa
+5.1,3.8,1.9,0.4,Iris-setosa
+4.8,3.0,1.4,0.3,Iris-setosa
+5.1,3.8,1.6,0.2,Iris-setosa
+4.6,3.2,1.4,0.2,Iris-setosa
+5.3,3.7,1.5,0.2,Iris-setosa
+5.0,3.3,1.4,0.2,Iris-setosa
+7.0,3.2,4.7,1.4,Iris-versicolor
+6.4,3.2,4.5,1.5,Iris-versicolor
+6.9,3.1,4.9,1.5,Iris-versicolor
+5.5,2.3,4.0,1.3,Iris-versicolor
+6.5,2.8,4.6,1.5,Iris-versicolor
+5.7,2.8,4.5,1.3,Iris-versicolor
+6.3,3.3,4.7,1.6,Iris-versicolor
+4.9,2.4,3.3,1.0,Iris-versicolor
+6.6,2.9,4.6,1.3,Iris-versicolor
+5.2,2.7,3.9,1.4,Iris-versicolor
+5.0,2.0,3.5,1.0,Iris-versicolor
+5.9,3.0,4.2,1.5,Iris-versicolor
+6.0,2.2,4.0,1.0,Iris-versicolor
+6.1,2.9,4.7,1.4,Iris-versicolor
+5.6,2.9,3.6,1.3,Iris-versicolor
+6.7,3.1,4.4,1.4,Iris-versicolor
+5.6,3.0,4.5,1.5,Iris-versicolor
+5.8,2.7,4.1,1.0,Iris-versicolor
+6.2,2.2,4.5,1.5,Iris-versicolor
+5.6,2.5,3.9,1.1,Iris-versicolor
+5.9,3.2,4.8,1.8,Iris-versicolor
+6.1,2.8,4.0,1.3,Iris-versicolor
+6.3,2.5,4.9,1.5,Iris-versicolor
+6.1,2.8,4.7,1.2,Iris-versicolor
+6.4,2.9,4.3,1.3,Iris-versicolor
+6.6,3.0,4.4,1.4,Iris-versicolor
+6.8,2.8,4.8,1.4,Iris-versicolor
+6.7,3.0,5.0,1.7,Iris-versicolor
+6.0,2.9,4.5,1.5,Iris-versicolor
+5.7,2.6,3.5,1.0,Iris-versicolor
+5.5,2.4,3.8,1.1,Iris-versicolor
+5.5,2.4,3.7,1.0,Iris-versicolor
+5.8,2.7,3.9,1.2,Iris-versicolor
+6.0,2.7,5.1,1.6,Iris-versicolor
+5.4,3.0,4.5,1.5,Iris-versicolor
+6.0,3.4,4.5,1.6,Iris-versicolor
+6.7,3.1,4.7,1.5,Iris-versicolor
+6.3,2.3,4.4,1.3,Iris-versicolor
+5.6,3.0,4.1,1.3,Iris-versicolor
+5.5,2.5,4.0,1.3,Iris-versicolor
+5.5,2.6,4.4,1.2,Iris-versicolor
+6.1,3.0,4.6,1.4,Iris-versicolor
+5.8,2.6,4.0,1.2,Iris-versicolor
+5.0,2.3,3.3,1.0,Iris-versicolor
+5.6,2.7,4.2,1.3,Iris-versicolor
+5.7,3.0,4.2,1.2,Iris-versicolor
+5.7,2.9,4.2,1.3,Iris-versicolor
+6.2,2.9,4.3,1.3,Iris-versicolor
+5.1,2.5,3.0,1.1,Iris-versicolor
+5.7,2.8,4.1,1.3,Iris-versicolor
+6.3,3.3,6.0,2.5,Iris-virginica
+5.8,2.7,5.1,1.9,Iris-virginica
+7.1,3.0,5.9,2.1,Iris-virginica
+6.3,2.9,5.6,1.8,Iris-virginica
+6.5,3.0,5.8,2.2,Iris-virginica
+7.6,3.0,6.6,2.1,Iris-virginica
+4.9,2.5,4.5,1.7,Iris-virginica
+7.3,2.9,6.3,1.8,Iris-virginica
+6.7,2.5,5.8,1.8,Iris-virginica
+7.2,3.6,6.1,2.5,Iris-virginica
+6.5,3.2,5.1,2.0,Iris-virginica
+6.4,2.7,5.3,1.9,Iris-virginica
+6.8,3.0,5.5,2.1,Iris-virginica
+5.7,2.5,5.0,2.0,Iris-virginica
+5.8,2.8,5.1,2.4,Iris-virginica
+6.4,3.2,5.3,2.3,Iris-virginica
+6.5,3.0,5.5,1.8,Iris-virginica
+7.7,3.8,6.7,2.2,Iris-virginica
+7.7,2.6,6.9,2.3,Iris-virginica
+6.0,2.2,5.0,1.5,Iris-virginica
+6.9,3.2,5.7,2.3,Iris-virginica
+5.6,2.8,4.9,2.0,Iris-virginica
+7.7,2.8,6.7,2.0,Iris-virginica
+6.3,2.7,4.9,1.8,Iris-virginica
+6.7,3.3,5.7,2.1,Iris-virginica
+7.2,3.2,6.0,1.8,Iris-virginica
+6.2,2.8,4.8,1.8,Iris-virginica
+6.1,3.0,4.9,1.8,Iris-virginica
+6.4,2.8,5.6,2.1,Iris-virginica
+7.2,3.0,5.8,1.6,Iris-virginica
+7.4,2.8,6.1,1.9,Iris-virginica
+7.9,3.8,6.4,2.0,Iris-virginica
+6.4,2.8,5.6,2.2,Iris-virginica
+6.3,2.8,5.1,1.5,Iris-virginica
+6.1,2.6,5.6,1.4,Iris-virginica
+7.7,3.0,6.1,2.3,Iris-virginica
+6.3,3.4,5.6,2.4,Iris-virginica
+6.4,3.1,5.5,1.8,Iris-virginica
+6.0,3.0,4.8,1.8,Iris-virginica
+6.9,3.1,5.4,2.1,Iris-virginica
+6.7,3.1,5.6,2.4,Iris-virginica
+6.9,3.1,5.1,2.3,Iris-virginica
+5.8,2.7,5.1,1.9,Iris-virginica
+6.8,3.2,5.9,2.3,Iris-virginica
+6.7,3.3,5.7,2.5,Iris-virginica
+6.7,3.0,5.2,2.3,Iris-virginica
+6.3,2.5,5.0,1.9,Iris-virginica
+6.5,3.0,5.2,2.0,Iris-virginica
+6.2,3.4,5.4,2.3,Iris-virginica
+5.9,3.0,5.1,1.8,Iris-virginica
+
diff --git a/datasets.cabal b/datasets.cabal
new file mode 100644
--- /dev/null
+++ b/datasets.cabal
@@ -0,0 +1,57 @@
+Name:                datasets
+Version:             0.1.0
+Synopsis:            Classical data sets for statistics and machine learning
+Description:         Classical machine learning and statistics datasets from
+                     the UCI Machine Learning Repository and other sources.
+                     .
+                     > import Numeric.Datasets (getDataset)
+                     > import Numeric.Datasets.Iris (iris)
+                     >
+                     > main = do
+                     >   irises <- getDataset iris
+                     >   print (length irises)
+                     >   print (head irises)
+
+License:             MIT
+License-file:        LICENSE
+Author:              Tom Nielsen <tanielsen@gmail.com>
+Maintainer:          Tom Nielsen <tanielsen@gmail.com>
+build-type:          Simple
+Cabal-Version: 	     >= 1.8
+homepage:            https://github.com/glutamate/datasets
+category:            Statistics, Machine Learning, Data Mining, Data
+
+Data-files:
+        datafiles/iris.data
+
+source-repository head
+  type:     git
+  location: https://github.com/glutamate/uci-datasets
+
+
+Library
+   ghc-options:       -Wall
+   hs-source-dirs:    src
+
+   Exposed-modules:
+                   Numeric.Datasets
+                 , Numeric.Datasets.Anscombe
+                 , Numeric.Datasets.OldFaithful
+                 , Numeric.Datasets.Abalone
+                 , Numeric.Datasets.Adult
+                 , Numeric.Datasets.BreastCancerWisconsin
+                 , Numeric.Datasets.Car
+                 , Numeric.Datasets.Iris
+                 , Numeric.Datasets.Wine
+
+   Build-depends:
+                 base                    >= 4.6 && < 5
+               , cassava
+               , HTTP
+               , hashable
+               , filepath
+               , bytestring
+               , directory
+               , vector
+               , text
+               , stringsearch
diff --git a/src/Numeric/Datasets.hs b/src/Numeric/Datasets.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Datasets.hs
@@ -0,0 +1,102 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Numeric.Datasets where
+
+import Network.HTTP
+import Data.Csv
+import System.FilePath
+import System.Directory
+import Data.Hashable
+import Data.Monoid
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.Vector as V
+
+import Data.Char (toUpper)
+import Text.Read (readMaybe)
+import Data.ByteString.Char8 (unpack)
+import qualified Data.ByteString.Lazy.Char8 as BL8
+import Data.ByteString.Lazy.Search (replace)
+
+import Paths_datasets (getDataFileName)
+-- * Using datasets
+
+-- |Load a dataset, using the system temporary directory as a cache
+getDataset :: Dataset a -> IO [a]
+getDataset ds = do
+  dir <- getTemporaryDirectory
+  ds $ dir </> "haskds"
+
+-- | A dataset is defined as a function from the caching directory to the IO action that loads the data
+type Dataset a = FilePath -- ^ Directory for caching downloaded datasets
+                 -> IO [a]
+
+-- * Defining datasets
+
+data Source = URL String | CabalDataFile FilePath
+
+
+-- |Define a dataset from a pre-processing function and a source for a CSV file
+csvDatasetPreprocess :: FromRecord a => (BL.ByteString -> BL.ByteString) -> Source -> Dataset a
+csvDatasetPreprocess preF src cacheDir = do
+
+  let parseFile contents = do
+        case decode NoHeader (preF contents) of
+          Right theData -> return $ V.toList theData
+          Left err -> fail err
+
+  getFileFromSource cacheDir src >>= parseFile
+
+-- |Define a dataset from a source for a CSV file
+csvDataset :: FromRecord a =>  Source -> Dataset a
+csvDataset  = csvDatasetPreprocess id
+
+getFileFromSource :: FilePath -> Source -> IO (BL.ByteString)
+getFileFromSource _ (CabalDataFile fnm) = do
+  fullpath <- getDataFileName fnm
+  BL.readFile fullpath
+getFileFromSource cacheDir (URL url) = do
+  createDirectoryIfMissing True cacheDir
+  let fnm = cacheDir </> "ds" <> show (hash url)
+      castRequest :: Request String -> Request BL.ByteString
+      castRequest r = Request (rqURI r) (rqMethod r) (rqHeaders r) ""
+
+  ex <- doesFileExist fnm
+  if ex
+     then BL.readFile fnm
+     else do
+       rsp <- simpleHTTP (castRequest $ getRequest url)
+       bs <- getResponseBody rsp
+       BL.writeFile fnm bs
+       return bs
+
+
+-- * Helper functions for parsing
+
+-- |Turn dashes to CamlCase
+dashToCamelCase :: String -> String
+dashToCamelCase ('-':c:cs) = toUpper c : dashToCamelCase cs
+dashToCamelCase (c:cs) = c : dashToCamelCase cs
+dashToCamelCase [] = []
+
+-- | Parse a field, first turning dashes to CamlCase
+parseDashToCamelField :: Read a => Field -> Parser a
+parseDashToCamelField s =
+  case readMaybe (dashToCamelCase $ unpack s) of
+    Just wc -> pure wc
+    Nothing -> fail "unknown"
+
+-- | parse somethign, based on its read instance
+parseReadField :: Read a => Field -> Parser a
+parseReadField s =
+  case readMaybe (unpack s) of
+    Just wc -> pure wc
+    Nothing -> fail "unknown"
+
+-- |Drop lines from a bytestring
+dropLines :: Int -> BL.ByteString -> BL.ByteString
+dropLines 0 s = s
+dropLines n s = dropLines (n-1) $ BL.tail $ BL8.dropWhile (/='\n') s
+
+-- | Turn US-style decimals  starting with a period (e.g. .2) into something Haskell can parse (e.g. 0.2)
+fixAmericanDecimals :: BL.ByteString -> BL.ByteString
+fixAmericanDecimals = replace ",." (",0."::BL.ByteString)
diff --git a/src/Numeric/Datasets/Abalone.hs b/src/Numeric/Datasets/Abalone.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Datasets/Abalone.hs
@@ -0,0 +1,39 @@
+{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}
+
+{-|
+
+Abalone data set
+
+UCI ML Repository link <https://archive.ics.uci.edu/ml/datasets/abalone>
+
+-}
+
+module Numeric.Datasets.Abalone where
+
+import Numeric.Datasets
+
+import Data.Csv
+import GHC.Generics
+
+data Sex = M | F | I
+  deriving (Show, Read, Eq, Generic)
+
+instance FromField Sex where
+  parseField = parseReadField
+
+data Abalone = Abalone
+  { sex :: Sex
+  , abaloneLength :: Double
+  , diameter :: Double
+  , height :: Double
+  , wholeWeight :: Double
+  , shuckedWeight :: Double
+  , visceraWeight :: Double
+  , shellWeight :: Double
+  , rings :: Int
+  } deriving (Show, Read, Generic)
+
+instance FromRecord Abalone
+
+abalone :: Dataset Abalone
+abalone = csvDataset $ URL "http://archive.ics.uci.edu/ml/machine-learning-databases/abalone/abalone.data"
diff --git a/src/Numeric/Datasets/Adult.hs b/src/Numeric/Datasets/Adult.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Datasets/Adult.hs
@@ -0,0 +1,102 @@
+{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}
+
+{-|
+
+Adult (AKA Census Income) dataset.
+
+UCI ML Repository link <http://archive.ics.uci.edu/ml/datasets/Adult>
+
+-}
+
+module Numeric.Datasets.Adult where
+
+import Numeric.Datasets
+
+import Data.Csv
+import GHC.Generics
+import Control.Applicative
+import Data.Text (Text, strip)
+
+data WorkClass = Private | SelfEmpNotInc | SelfEmpInc | FederalGov
+               | LocalGov | StateGov | WithoutPay | NeverWorked
+  deriving (Show, Read, Eq, Generic)
+
+instance FromField WorkClass where
+  parseField = parseDashToCamelField
+
+
+data MaritalStatus = MarriedCivSpouse | Divorced | NeverMarried
+                   | Separated | Widowed | MarriedSpouseAbsent | MarriedAFSpouse
+  deriving (Show, Read, Eq, Generic)
+
+instance FromField MaritalStatus where
+--  parseField "Married-AF-spouse" = pure MarriedAFSpouse
+  parseField s = parseDashToCamelField s
+
+data Occupation = TechSupport | CraftRepair | OtherService | Sales | ExecManagerial | ProfSpecialty
+                | HandlersCleaners | MachineOpInspct | AdmClerical | FarmingFishing | TransportMoving
+                | PrivHouseServ | ProtectiveServ | ArmedForces
+  deriving (Show, Read, Eq, Generic)
+
+instance FromField Occupation where
+--  parseField "ArmedForces" = pure ArmedForces
+  parseField s = parseDashToCamelField s
+
+data Relationship = Wife | OwnChild | Husband | NotInFamily | OtherRelative | Unmarried
+  deriving (Show, Read, Eq, Generic)
+
+instance FromField Relationship where
+  parseField s = parseDashToCamelField s
+
+data Race = White | AsianPacIslander | AmerIndianEskimo | Other | Black
+  deriving (Show, Read, Eq, Generic)
+
+instance FromField Race where
+  parseField s = parseDashToCamelField s
+
+data Sex = Female | Male
+  deriving (Show, Read, Eq, Generic)
+
+instance FromField Sex where
+  parseField s = parseDashToCamelField s
+
+data Income = GT50K | LE50K
+  deriving (Show, Read, Eq, Generic)
+
+instance FromField Income where
+  parseField " >50K" = pure GT50K
+  parseField " <=50K" = pure LE50K
+  parseField " >50K." = pure GT50K
+  parseField " <=50K." = pure LE50K
+  parseField ">50K" = pure GT50K
+  parseField "<=50K" = pure LE50K
+  parseField _ = fail "unknown income"
+
+data Adult = Adult
+  { age :: Int
+  , workClass :: Maybe WorkClass
+  , finalWeight :: Int
+  , education :: Text
+  , educationNum :: Int
+  , maritalStatus :: MaritalStatus
+  , occupation :: Maybe Occupation
+  , relationship :: Relationship
+  , race :: Race
+  , sex :: Sex
+  , capitalGain :: Int
+  , capitalLoss :: Int
+  , hoursPerWeek :: Int
+  , nativeCountry :: Text
+  , income :: Income
+  } deriving (Show, Read, Generic)
+
+instance FromRecord Adult where
+  parseRecord v = Adult <$> v .! 0 <*> (v.! 1 <|> return Nothing) <*> v.!2 <*> (strip <$> v.!3)
+                        <*> v.!4 <*> v.!5<*> (v.!6 <|> return Nothing) <*> v.!7 <*> v.!8
+                        <*> v.!9 <*> v.!10 <*> v.!11 <*> v.!12<*> v.!13<*> v.!14
+
+adult :: Dataset Adult
+adult = csvDataset $ URL "http://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data"
+
+adultTestSet :: Dataset Adult
+adultTestSet = csvDatasetPreprocess (dropLines 1) $ URL "http://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.test"
diff --git a/src/Numeric/Datasets/Anscombe.hs b/src/Numeric/Datasets/Anscombe.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Datasets/Anscombe.hs
@@ -0,0 +1,73 @@
+{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}
+
+{-|
+
+Anscombe's quartet
+
+Four datasets with nearly identical statistical properties
+
+Wikipedia article: <https://en.wikipedia.org/wiki/Anscombe%27s_quartet>
+
+-}
+
+module Numeric.Datasets.Anscombe where
+
+anscombe :: [[(Double,Double)]]
+anscombe = [anscombe1, anscombe2, anscombe3, anscombe4]
+
+anscombe1, anscombe2, anscombe3, anscombe4 :: [(Double, Double)]
+anscombe1 = [
+  (10,8.04),
+  (8,6.95),
+  (13,7.58),
+  (9,8.81),
+  (11,8.33),
+  (14,9.96),
+  (6,7.24),
+  (4,4.26),
+  (12,10.84),
+  (7,4.82),
+  (5,5.68)
+ ]
+
+anscombe2 = [
+  (10,9.14),
+  (8,8.14),
+  (13,8.74),
+  (9,8.77),
+  (11,9.26),
+  (14,8.1),
+  (6,6.13),
+  (4,3.1),
+  (12,9.13),
+  (7,7.26),
+  (5,4.74)
+ ]
+
+anscombe3 = [
+  (10,7.46),
+  (8,6.77),
+  (13,12.74),
+  (9,7.11),
+  (11,7.81),
+  (14,8.84),
+  (6,6.08),
+  (4,5.39),
+  (12,8.15),
+  (7,6.42),
+  (5,5.73)
+ ]
+
+anscombe4 = [
+  (8,6.58),
+  (8,5.76),
+  (8,7.71),
+  (8,8.84),
+  (8,8.47),
+  (8,7.04),
+  (8,5.25),
+  (19,12.5),
+  (8,5.56),
+  (8,7.91),
+  (8,6.89)
+ ]
diff --git a/src/Numeric/Datasets/BreastCancerWisconsin.hs b/src/Numeric/Datasets/BreastCancerWisconsin.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Datasets/BreastCancerWisconsin.hs
@@ -0,0 +1,99 @@
+{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}
+
+{-|
+
+Breast Cancer Wisconsin (Diagnostic) Data Set
+
+Repository link: <http://mlr.cs.umass.edu/ml/datasets/Breast+Cancer+Wisconsin+%28Diagnostic%29>
+
+-}
+
+module Numeric.Datasets.BreastCancerWisconsin where
+
+import Numeric.Datasets
+
+import Data.Csv
+import GHC.Generics
+import Control.Applicative
+
+
+data Diagnosis = Malignant | Benign deriving (Show, Read, Eq, Generic)
+
+data Prognosis = Recurrent | Nonrecurrent deriving (Show, Read, Eq, Generic)
+
+intToDiagnosis :: Int -> Diagnosis
+intToDiagnosis 2 = Benign
+intToDiagnosis 4 = Malignant
+intToDiagnosis _ = error "unknown diagnosis code"
+
+data BreastCancerEntry = BreastCancerEntry
+ { sampleCodeNumber :: Int
+ , clumpThickness :: Int
+ , uniformityCellSize :: Int
+ , uniformityCellShape :: Int
+ , marginalAdhesion :: Int
+ , singleEpithelialCellSize :: Int
+ , bareNuclei :: Maybe Int
+ , blandChromatin :: Int
+ , normalNucleoli :: Int
+ , mitosis :: Int
+ , sampleClass :: Diagnosis
+ } deriving (Show, Read, Generic)
+
+instance FromRecord BreastCancerEntry where
+  parseRecord v = BreastCancerEntry <$> v .! 0 <*> v .! 1 <*> v .! 2 <*> v .! 3 <*> v .! 4 <*> v .! 5 <*> (v .! 6 <|> return Nothing) <*> v .! 7  <*> v .! 8  <*> v .! 9  <*> (intToDiagnosis <$> v .! 10)
+
+breastCancerDatabase :: Dataset BreastCancerEntry
+breastCancerDatabase = csvDataset
+   $ URL "http://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data"
+
+data DiagnosticBreastCancer = DiagnosticBreastCancer
+  { diagnosticID :: Int
+  , diagnosis :: Diagnosis
+  , diagnosticCells :: CellFeatures
+  } deriving (Show, Read, Generic)
+
+data PrognosticBreastCancer = PrognosticBreastCancer
+  { prognosticID :: Int
+  , prognosis :: Prognosis
+  , prognosticCells :: CellFeatures
+  } deriving (Show, Read, Generic)
+
+data CellFeatures = CellFeatures
+  { radius :: Double
+  , perimeter :: Double
+  , area :: Double
+  , smoothness :: Double
+  , compactness :: Double
+  , concavity :: Double
+  , concavePoints :: Double
+  , symmetry :: Double
+  , fractalDimension :: Double
+  } deriving (Show, Read, Generic)
+
+charToDiagnosis :: String -> Diagnosis
+charToDiagnosis "M" = Malignant
+charToDiagnosis "B" = Benign
+charToDiagnosis _ = error "unknown diagnosis"
+
+charToPrognosis :: String -> Prognosis
+charToPrognosis "N" = Nonrecurrent
+charToPrognosis "R" = Recurrent
+charToPrognosis _ = error "unknown diagnosis"
+
+instance FromRecord DiagnosticBreastCancer where
+  parseRecord v = DiagnosticBreastCancer <$> v .! 0 <*> (charToDiagnosis <$> v .! 1) <*> parseRecord v
+
+instance FromRecord PrognosticBreastCancer where
+  parseRecord v = PrognosticBreastCancer <$> v .! 0 <*> (charToPrognosis <$> v .! 1) <*> parseRecord v
+
+instance FromRecord CellFeatures where
+  parseRecord v = CellFeatures <$> v .! 2 <*> v .! 3 <*> v .! 4 <*> v .! 5 <*> v .! 6  <*> v .! 7  <*> v .! 8  <*> v .! 9  <*> v .! 10
+
+diagnosticBreastCancer :: Dataset DiagnosticBreastCancer
+diagnosticBreastCancer = csvDataset
+   $ URL "http://mlr.cs.umass.edu/ml/machine-learning-databases/breast-cancer-wisconsin/wdbc.data"
+
+prognosticBreastCancer :: Dataset PrognosticBreastCancer
+prognosticBreastCancer = csvDataset
+   $ URL "http://mlr.cs.umass.edu/ml/machine-learning-databases/breast-cancer-wisconsin/wpbc.data"
diff --git a/src/Numeric/Datasets/Car.hs b/src/Numeric/Datasets/Car.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Datasets/Car.hs
@@ -0,0 +1,68 @@
+{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}
+
+{-|
+
+Car dataset
+
+UCI ML Repository link <https://archive.ics.uci.edu/ml/datasets/car>
+
+-}
+
+module Numeric.Datasets.Car where
+
+import Numeric.Datasets
+
+import Data.Csv
+import GHC.Generics
+
+data RelScore = Low | Med | High | VeryHigh deriving (Show, Read, Eq, Generic)
+
+instance FromField RelScore where
+  parseField "vhigh" = pure VeryHigh
+  parseField "high" = pure High
+  parseField "med" = pure Med
+  parseField "low" = pure Low
+  parseField _ = fail "unknown relative score"
+
+data RelSize = Small | Medium | Big deriving (Show, Read, Eq, Generic)
+
+instance FromField RelSize where
+  parseField "small" = pure Small
+  parseField "med" = pure Medium
+  parseField "big" = pure Big
+  parseField _ = fail "unknown relative size"
+
+data Acceptability = Unacceptable | Acceptable | Good | VeryGood deriving (Show, Read, Eq, Generic)
+
+instance FromField Acceptability where
+  parseField "unacc" = pure Unacceptable
+  parseField "acc" = pure Acceptable
+  parseField "good" = pure Good
+  parseField "vgood" = pure VeryGood
+  parseField _ = fail "unknown acceptability"
+
+data Count = N Int | NOrMore Int | More deriving (Show, Read, Eq, Generic)
+
+instance FromField Count where
+  parseField "more" = pure More
+  parseField "5more" = pure (NOrMore 5)
+  parseField "2" = pure (N 2)
+  parseField "3" = pure (N 3)
+  parseField "4" = pure (N 4)
+  parseField _ = fail "unknown count"
+
+data Car = Car
+  { buying :: RelScore
+  , maintenance :: RelScore
+  , doors :: Count
+  , persons :: Count
+  , luggageBoot :: RelSize
+  , safety :: RelScore
+  , acceptability:: Acceptability
+  } deriving (Show, Read, Generic)
+
+instance FromRecord Car
+
+car :: Dataset Car
+car = csvDataset
+          $ URL "http://archive.ics.uci.edu/ml/machine-learning-databases/car/car.data"
diff --git a/src/Numeric/Datasets/Iris.hs b/src/Numeric/Datasets/Iris.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Datasets/Iris.hs
@@ -0,0 +1,38 @@
+{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}
+
+{-|
+
+The classical Iris dataset, due to R.A. Fisher.
+
+UCI ML Repository link <https://archive.ics.uci.edu/ml/datasets/Iris>
+
+-}
+
+module Numeric.Datasets.Iris where
+
+import Numeric.Datasets
+
+import Data.Csv
+import GHC.Generics
+
+data IrisClass = Setosa | Versicolor | Virginica
+  deriving (Show, Read, Eq, Generic)
+
+instance FromField IrisClass where
+  parseField "Iris-setosa" = pure Setosa
+  parseField "Iris-versicolor" = pure Versicolor
+  parseField "Iris-virginica" = pure Virginica
+  parseField _ = fail "unknown iris class"
+
+data Iris = Iris
+  { sepalLength :: Double
+  , sepalWidth :: Double
+  , petalLength :: Double
+  , petalWidth :: Double
+  , irisClass :: IrisClass
+  } deriving (Show, Read, Generic)
+
+instance FromRecord Iris
+
+iris :: Dataset Iris
+iris = csvDataset $ CabalDataFile "datafiles/iris.data"
diff --git a/src/Numeric/Datasets/OldFaithful.hs b/src/Numeric/Datasets/OldFaithful.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Datasets/OldFaithful.hs
@@ -0,0 +1,246 @@
+{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}
+
+{-|
+
+Old Faithful Geyser Eruption data
+
+Article: http://web.pdx.edu/~jfreder/M212/oldfaithful.pdf
+
+These data from: <http://www2.stat.duke.edu/courses/Fall02/sta290/datasets/geyser>
+
+For more data, see <http://www.geyserstudy.org/geyser.aspx?pGeyserNo=OLDFAITHFUL>
+
+-}
+
+module Numeric.Datasets.OldFaithful where
+
+data OldFaithful = OF
+  { recordingDay :: Int -- ^ Recording day. 1-8: 1978, 16-23: 1979
+  , waiting :: Double -- ^ waiting time until next eruption
+  , duration :: Double -- ^ duration of eruption in minutes
+  }
+-- The first comp
+oldFaithful :: [OldFaithful]
+oldFaithful =
+  [ OF  1 78 4.4
+  , OF  1 74 3.9
+  , OF  1 68 4.0
+  , OF  1 76 4.0
+  , OF  1 80 3.5
+  , OF  1 84 4.1
+  , OF  1 50 2.3
+  , OF  1 93 4.7
+  , OF  1 55 1.7
+  , OF  1 76 4.9
+  , OF  1 58 1.7
+  , OF  1 74 4.6
+  , OF  1 75 3.4
+  , OF  2 80 4.3
+  , OF  2 56 1.7
+  , OF  2 80 3.9
+  , OF  2 69 3.7
+  , OF  2 57 3.1
+  , OF  2 90 4.0
+  , OF  2 42 1.8
+  , OF  2 91 4.1
+  , OF  2 51 1.8
+  , OF  2 79 3.2
+  , OF  2 53 1.9
+  , OF  2 82 4.6
+  , OF  2 51 2.0
+  , OF  3 76 4.5
+  , OF  3 82 3.9
+  , OF  3 84 4.3
+  , OF  3 53 2.3
+  , OF  3 86 3.8
+  , OF  3 51 1.9
+  , OF  3 85 4.6
+  , OF  3 45 1.8
+  , OF  3 88 4.7
+  , OF  3 51 1.8
+  , OF  3 80 4.6
+  , OF  3 49 1.9
+  , OF  3 82 3.5
+  , OF  4 75 4.0
+  , OF  4 73 3.7
+  , OF  4 67 3.7
+  , OF  4 68 4.3
+  , OF  4 86 3.6
+  , OF  4 72 3.8
+  , OF  4 75 3.8
+  , OF  4 75 3.8
+  , OF  4 66 2.5
+  , OF  4 84 4.5
+  , OF  4 70 4.1
+  , OF  4 79 3.7
+  , OF  4 60 3.8
+  , OF  4 86 3.4
+  , OF  5 71 4.0
+  , OF  5 67 2.3
+  , OF  5 81 4.4
+  , OF  5 76 4.1
+  , OF  5 83 4.3
+  , OF  5 76 3.3
+  , OF  5 55 2.0
+  , OF  5 73 4.3
+  , OF  5 56 2.9
+  , OF  5 83 4.6
+  , OF  5 57 1.9
+  , OF  5 71 3.6
+  , OF  5 72 3.7
+  , OF  5 77 3.7
+  , OF  6 55 1.8
+  , OF  6 75 4.6
+  , OF  6 73 3.5
+  , OF  6 70 4.0
+  , OF  6 83 3.7
+  , OF  6 50 1.7
+  , OF  6 95 4.6
+  , OF  6 51 1.7
+  , OF  6 82 4.0
+  , OF  6 54 1.8
+  , OF  6 83 4.4
+  , OF  6 51 1.9
+  , OF  6 80 4.6
+  , OF  6 78 2.9
+  , OF  7 81 3.5
+  , OF  7 53 2.0
+  , OF  7 89 4.3
+  , OF  7 44 1.8
+  , OF  7 78 4.1
+  , OF  7 61 1.8
+  , OF  7 73 4.7
+  , OF  7 75 4.2
+  , OF  7 73 3.9
+  , OF  7 76 4.3
+  , OF  7 55 1.8
+  , OF  7 86 4.5
+  , OF  7 48 2.0
+  , OF  8 77 4.2
+  , OF  8 73 4.4
+  , OF  8 70 4.1
+  , OF  8 88 4.1
+  , OF  8 75 4.0
+  , OF  8 83 4.1
+  , OF  8 61 2.7
+  , OF  8 78 4.6
+  , OF  8 61 1.9
+  , OF  8 81 4.5
+  , OF  8 51 2.0
+  , OF  8 80 4.8
+  , OF  8 79 4.1
+  , OF 16 82 4.1
+  , OF 16 80 4.2
+  , OF 16 76 4.5
+  , OF 16 56 1.9
+  , OF 16 82 4.7
+  , OF 16 47 2.0
+  , OF 16 76 4.7
+  , OF 16 61 2.5
+  , OF 16 75 4.3
+  , OF 16 72 4.4
+  , OF 16 74 4.4
+  , OF 16 69 4.3
+  , OF 16 78 4.6
+  , OF 16 52 2.1
+  , OF 17 91 4.8
+  , OF 17 66 4.1
+  , OF 17 71 4.0
+  , OF 17 75 4.0
+  , OF 17 81 4.4
+  , OF 17 77 4.1
+  , OF 17 74 4.3
+  , OF 17 70 4.0
+  , OF 17 83 3.9
+  , OF 17 53 3.2
+  , OF 17 82 4.5
+  , OF 17 62 2.2
+  , OF 17 73 4.7
+  , OF 17 84 4.6
+  , OF 18 58 2.2
+  , OF 18 82 4.8
+  , OF 18 77 4.3
+  , OF 18 75 3.8
+  , OF 18 77 4.0
+  , OF 18 77 4.1
+  , OF 18 53 1.8
+  , OF 18 75 4.4
+  , OF 18 78 4.0
+  , OF 18 51 2.2
+  , OF 18 81 5.1
+  , OF 18 52 1.9
+  , OF 18 76 5.0
+  , OF 18 73 4.4
+  , OF 19 84 4.5
+  , OF 19 72 3.8
+  , OF 19 89 4.3
+  , OF 19 75 4.4
+  , OF 19 57 2.2
+  , OF 19 81 4.8
+  , OF 19 49 1.9
+  , OF 19 87 4.7
+  , OF 19 43 1.8
+  , OF 19 94 4.8
+  , OF 19 45 2.0
+  , OF 19 81 4.4
+  , OF 19 59 2.5
+  , OF 19 82 4.3
+  , OF 20 80 4.4
+  , OF 20 54 1.9
+  , OF 20 75 4.7
+  , OF 20 73 4.3
+  , OF 20 57 2.2
+  , OF 20 80 4.7
+  , OF 20 51 2.3
+  , OF 20 77 4.6
+  , OF 20 66 3.3
+  , OF 20 77 4.2
+  , OF 20 60 2.9
+  , OF 20 86 4.6
+  , OF 20 62 3.3
+  , OF 20 75 4.2
+  , OF 20 67 2.6
+  , OF 20 69 4.6
+  , OF 21 84 3.7
+  , OF 21 58 1.8
+  , OF 21 90 4.7
+  , OF 21 82 4.5
+  , OF 21 71 4.5
+  , OF 21 80 4.8
+  , OF 21 51 2.0
+  , OF 21 80 4.8
+  , OF 21 62 1.9
+  , OF 21 84 4.7
+  , OF 21 51 2.0
+  , OF 21 81 5.1
+  , OF 21 83 4.3
+  , OF 21 84 4.8
+  , OF 22 72 3.0
+  , OF 22 54 2.1
+  , OF 22 75 4.6
+  , OF 22 74 4.0
+  , OF 22 51 2.2
+  , OF 22 91 5.1
+  , OF 22 60 2.9
+  , OF 22 80 4.3
+  , OF 22 54 2.1
+  , OF 22 80 4.7
+  , OF 22 70 4.5
+  , OF 22 60 1.7
+  , OF 22 86 4.2
+  , OF 22 78 4.3
+  , OF 23 51 1.7
+  , OF 23 83 4.4
+  , OF 23 76 4.2
+  , OF 23 51 2.2
+  , OF 23 90 4.7
+  , OF 23 71 4.0
+  , OF 23 49 1.8
+  , OF 23 88 4.7
+  , OF 23 52 1.8
+  , OF 23 79 4.5
+  , OF 23 61 2.1
+  , OF 23 81 4.2
+  , OF 23 48 2.1
+  , OF 23 84 5.2
+  , OF 23 63 2.0 ]
diff --git a/src/Numeric/Datasets/Wine.hs b/src/Numeric/Datasets/Wine.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Datasets/Wine.hs
@@ -0,0 +1,40 @@
+{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}
+
+{-|
+
+Wine Data set
+
+UCI ML Repository link <http://mlr.cs.umass.edu/ml/datasets/Wine>
+
+-}
+
+module Numeric.Datasets.Wine where
+
+import Numeric.Datasets
+
+import Data.Csv
+import GHC.Generics
+
+data Wine = Wine
+  { wineClass :: Int
+  , alcohol :: Double
+  , malicAcid :: Double
+  , ash :: Double
+  , ashAlcalinity :: Double
+  , magnesium :: Double
+  , totalPhenols :: Double
+  , flavanoids :: Double
+  , nonflavanoidPhenols :: Double
+  , proanthocyanins :: Double
+  , colorIntensity :: Double
+  , hue :: Double
+  , dilutedOD280toOD315 :: Double
+  , proline :: Int
+  } deriving (Show, Read, Generic)
+
+instance FromRecord Wine
+
+wine :: Dataset Wine
+wine = csvDatasetPreprocess
+            fixAmericanDecimals
+            $ URL "http://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data"
