diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+0.1.1.2:
+
+* add testsuite based on doctest comments and doctest-extract
+
 0.1:
 
 * Hermite1 interpolation: different order of coefficients
diff --git a/Makefile b/Makefile
new file mode 100644
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,8 @@
+run-test:	update-test
+	runhaskell Setup configure --user --enable-test -fbuildExamples -flapack
+	runhaskell Setup build
+	runhaskell Setup haddock
+	runhaskell Setup test --show-details=always
+
+update-test:
+	doctest-extract -i src/ -o test/ --module-prefix Test --executable-main=Test.hs $$(cat test-module.list)
diff --git a/example/Fit.hs b/example/Fit.hs
--- a/example/Fit.hs
+++ b/example/Fit.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE Rank2Types #-}
 module Main where
 
@@ -8,19 +9,23 @@
 import qualified Numeric.Interpolation.Type as Type
 
 import qualified Numeric.LAPACK.Singular as Singular
-import qualified Numeric.LAPACK.ShapeStatic as ShapeStatic
 import qualified Numeric.LAPACK.Matrix.Shape as MatrixShape
 import qualified Numeric.LAPACK.Matrix.BandedHermitianPositiveDefinite
                                                        as BandedSPD
 import qualified Numeric.LAPACK.Matrix.BandedHermitian as BandedHermitian
+import qualified Numeric.LAPACK.Matrix.Banded as Banded
 import qualified Numeric.LAPACK.Matrix.Array as ArrMatrix
 import qualified Numeric.LAPACK.Matrix as Matrix
 import qualified Numeric.LAPACK.Vector as Vector
+import Numeric.LAPACK.Matrix ((#\|))
+import Numeric.LAPACK.Vector (Vector)
 
 import qualified Type.Data.Num.Unary as Unary
 import Type.Base.Proxy (Proxy)
 
 import qualified Data.Array.Comfort.Storable as Array
+import qualified Data.Array.Comfort.Container as Container
+import qualified Data.Array.Comfort.Shape.Static as ShapeStatic
 import qualified Data.Array.Comfort.Shape as Shape
 
 import qualified Graphics.Gnuplot.Advanced as GP
@@ -39,11 +44,11 @@
 import Data.Monoid ((<>))
 
 
-type BandedHermitianMatrix k =
-       BandedHermitian.BandedHermitian k Matrix.ShapeInt
-type Matrix = Matrix.General Matrix.ShapeInt Matrix.ShapeInt
-type Vector = Vector.Vector Matrix.ShapeInt
-type ShortVector k = Vector.Vector (ShapeStatic.ZeroBased k)
+{- |
+We use @'Container.Shape' []@ for distinction.
+We could use 'Matrix.ShapeInt' as well.
+-}
+type BasicMatrix = Matrix.General Matrix.ShapeInt (Container.Shape [])
 
 
 noisy :: [(Double, Double)]
@@ -55,24 +60,23 @@
       (randomRs (-0.2,0.2) (mkStdGen 42))
 
 basisMatrixFull ::
-   Type.T Double Double ny -> [Double] -> [Double] -> Matrix Double
+   Type.T Double Double ny -> [Double] -> [Double] -> BasicMatrix Double
 basisMatrixFull typ xs txs0 =
    let txs = Vector.autoFromList txs0
-   in  Matrix.fromColumns (Array.shape txs) $
+   in  Matrix.fromColumnContainer (Array.shape txs) $
        map (flip Array.map txs . Piecewise.interpolateConstantExt typ) $
        Type.basisFunctions typ xs
 
 zipRowsWith :: (a -> b -> c) -> [a] -> [[b]] -> [c]
 zipRowsWith f as bs = concat $ zipWith (map . f) as bs
 
--- ToDo: generalize shapes
 basisMatrixSparse ::
-   Type.T Double Double ny -> [Double] -> [Double] -> Matrix Double
+   Type.T Double Double ny -> [Double] -> [Double] -> BasicMatrix Double
 basisMatrixSparse typ xs txs =
    Matrix.fromRowMajor $
    Array.fromAssociations 0
       (Shape.ZeroBased $ length txs,
-       Shape.ZeroBased $ length $ Type.basisFunctions typ xs) $
+       Container.toShape $ Type.basisFunctions typ xs) $
    zipRowsWith (\k (j,x) -> ((k,j),x)) [0..] $
    map (Type.sampleBasisFunctions typ xs) txs
 
@@ -99,34 +103,31 @@
 
 
 mulSparseMatrixVector ::
-   Int -> [[(Int, Double)]] -> [Double] -> Vector Double
-mulSparseMatrixVector size samples tys =
+   (Shape.Indexed shape) =>
+   shape -> [[(Shape.Index shape, Double)]] ->
+   [Double] -> Vector shape Double
+mulSparseMatrixVector shape samples tys =
    Array.accumulate (+)
-      (Vector.zero (Matrix.shapeInt size))
+      (Vector.zero shape)
       (zipRowsWith (\ty (k,y) -> (k, y*ty)) tys samples)
 
-{- ToDo:
-use index type (ZeroInt, Enumeration Order)
-with Order = Absolute | Derivative
-Problem: not all interpolation types use derivatives
--}
 shortVector ::
    (Unary.Natural k) =>
-   Proxy k -> [(Int, Double)] -> (Int, ShortVector k Double)
+   Proxy k -> [(Int, Double)] -> (Int, Vector (ShapeStatic.ZeroBased k) Double)
 shortVector width xs =
    let i0 = minimum $ map fst xs
    in (i0,
---       Array.fromAssociations 0 Shape.static $
        Array.reshape Shape.static $
-       Array.fromAssociations 0 (Matrix.shapeInt $ Unary.integralFromProxy width) $
+       Array.fromAssociations 0
+          (Matrix.shapeInt $ Unary.integralFromProxy width) $
        map (mapFst (subtract i0)) xs)
 
 bandedGramian ::
-   (Unary.Natural k) =>
-   Int -> Proxy (Unary.Succ k) ->
-   [[(Int, Double)]] -> BandedHermitianMatrix k Double
-bandedGramian size width samples =
-   BandedHermitian.sumRank1 MatrixShape.ColumnMajor (Matrix.shapeInt size) $
+   (Shape.Indexed shape, Shape.Index shape ~ Int, Unary.Natural k) =>
+   shape -> Proxy (Unary.Succ k) ->
+   [[(Int, Double)]] -> Banded.HermitianPosSemidef k shape Double
+bandedGramian shape width samples =
+   BandedHermitian.sumRank1 MatrixShape.ColumnMajor shape $
    map ((,) 1 . shortVector width) samples
 
 reifyPositive ::
@@ -137,15 +138,16 @@
    Type.T Double Double ny ->
    [Double] -> [(Double, Double)] -> Nodes.T Double ny
 fitBanded typ xs target =
-   let size = length $ Type.basisFunctions typ xs
+   let shape = Container.toShape $ Type.basisFunctions typ xs
        (txs, tys) = unzip target
        samples = map (Type.sampleBasisFunctions typ xs) txs
-   in reifyPositive (toInteger $ Type.basisOverlap typ) 
+   in reifyPositive
+         (toInteger $ Type.basisOverlap typ)
          (\width ->
             Type.coefficientsToInterpolator typ xs $ Vector.toList $
-            Matrix.unliftColumn MatrixShape.ColumnMajor
-               (BandedSPD.solve (bandedGramian size width samples)) $
-            mulSparseMatrixVector size samples tys)
+            BandedSPD.assureFullRank (bandedGramian shape width samples)
+            #\|
+            mulSparseMatrixVector shape samples tys)
 
 bandedDiff ::
    (ny -> ny -> Double) ->
diff --git a/interpolation.cabal b/interpolation.cabal
--- a/interpolation.cabal
+++ b/interpolation.cabal
@@ -1,10 +1,11 @@
+Cabal-Version:    2.2
 Name:             interpolation
-Version:          0.1.1.1
-License:          BSD3
+Version:          0.1.1.2
+License:          BSD-3-Clause
 License-File:     LICENSE
 Author:           Henning Thielemann
 Maintainer:       Henning Thielemann <haskell@henning-thielemann.de>
-Homepage:         http://hub.darcs.net/thielema/interpolation/
+Homepage:         https://hub.darcs.net/thielema/interpolation/
 Category:         Math
 Synopsis:         piecewise linear and cubic Hermite interpolation
 Description:
@@ -33,10 +34,11 @@
   Most of the package dependencies are only needed for the examples
   and are only installed if you enable to build them.
 Tested-With:      GHC==7.4.2, GHC==7.6.3, GHC==7.8.4, GHC==7.10.1
-Cabal-Version:    >=1.8
 Build-Type:       Simple
 Extra-Source-Files:
   ChangeLog
+  Makefile
+  test-module.list
 
 Flag buildExamples
   description: Build example executables
@@ -47,13 +49,13 @@
   default:     True
 
 Source-Repository this
-  Tag:         0.1.1.1
+  Tag:         0.1.1.2
   Type:        darcs
-  Location:    http://hub.darcs.net/thielema/interpolation/
+  Location:    https://hub.darcs.net/thielema/interpolation/
 
 Source-Repository head
   Type:        darcs
-  Location:    http://hub.darcs.net/thielema/interpolation/
+  Location:    https://hub.darcs.net/thielema/interpolation/
 
 Library
   Build-Depends:
@@ -62,6 +64,7 @@
 
   GHC-Options:      -Wall
   Hs-Source-Dirs:   src, private
+  Default-Language: Haskell98
   Exposed-Modules:
     Numeric.Interpolation.NodeList
     Numeric.Interpolation.Piece
@@ -81,6 +84,7 @@
   Other-Modules:       Plot2DExtra
   Hs-Source-Dirs:      example
   GHC-Options:         -Wall
+  Default-Language:    Haskell98
   If flag(buildExamples)
     Build-Depends:
       interpolation,
@@ -95,12 +99,14 @@
   Other-Modules:       Plot2DExtra
   Hs-Source-Dirs:      example
   GHC-Options:         -Wall
+  Default-Language:    Haskell98
   If flag(buildExamples) && flag(lapack)
     Build-Depends:
       interpolation,
-      lapack >=0.3 && <0.4,
+      lapack >=0.4 && <0.5,
       tfp >=1.0 && <1.1,
-      comfort-array >=0.4 && <0.5,
+      comfort-array-shape >=0.0 && <0.1,
+      comfort-array >=0.5.1 && <0.6,
       random >=1.0 && <1.2,
       gnuplot >=0.5.6 && <0.6,
       utility-ht >=0.0.9 && <0.1,
@@ -112,14 +118,18 @@
   Type:                exitcode-stdio-1.0
   Main-Is:             Test.hs
   Other-Modules:
-    Test.Piece
-    Test.Sample
-    Test.Overlap
+    Test.Numeric.Interpolation.Type
+    Test.Numeric.Interpolation.NodeList
+    Test.Numeric.Interpolation.Piece
+    Test.Numeric.Interpolation.Piecewise
     Numeric.Interpolation.Private.Piece
   Hs-Source-Dirs:      test, private
   GHC-Options:         -Wall
+  Default-Language:    Haskell98
   Build-Depends:
     interpolation,
+    doctest-exitcode-stdio >=0.0 && <0.1,
+    doctest-lib >=0.1 && <0.2,
     QuickCheck >=2.4 && <3,
     utility-ht >=0.0.9 && <0.1,
     array >=0.4 && <0.6,
diff --git a/src/Numeric/Interpolation/NodeList.hs b/src/Numeric/Interpolation/NodeList.hs
--- a/src/Numeric/Interpolation/NodeList.hs
+++ b/src/Numeric/Interpolation/NodeList.hs
@@ -16,22 +16,40 @@
 
 import Prelude hiding (lookup)
 
+{- $setup
+>>> import qualified Numeric.Interpolation.NodeList as Nodes
+>>> import qualified Data.Traversable as Trav
+>>> import qualified Data.Foldable as Fold
+>>> import qualified Data.List as List
+>>> import Data.Tuple.HT (mapSnd)
+>>> import Data.Char (ord)
+-}
 
+
 data T x y = Interval | Node (x, y) (T x y) (T x y)
    deriving (Eq, Ord, Show)
 
+{- |
+prop> \xs -> map (mapSnd ord) xs == Nodes.toList (fmap ord (Nodes.fromList (xs::[(Integer,Char)])))
+-}
 instance Functor (T x) where
    fmap f =
       let go Interval = Interval
           go (Node (x,y) l r) = Node (x, f y) (go l) (go r)
       in  go
 
+{- |
+prop> \xs -> map snd xs == Fold.toList (Nodes.fromList (xs::[(Integer,Char)]))
+-}
 instance Foldable (T x) where
    foldMap f =
       let go Interval = mempty
           go (Node (_x,y) l r) = go l <> f y <> go r
       in  go
 
+{- |
+prop> \x xs -> let f acc y = (acc+y,acc) in List.mapAccumL f x (map snd xs) == mapSnd Fold.toList (Trav.mapAccumL f x (Nodes.fromList (xs::[(Int,Integer)])))
+-}
 instance Traversable (T x) where
    traverse f =
       let go Interval = pure Interval
@@ -55,15 +73,35 @@
        rep (n,xyns) = if null xyns then n else rep $ merge n xyns
    in  rep . merge Interval . map (flip (,) Interval)
 
+{- |
+prop> \x y -> Nodes.singleton x y == Nodes.fromList [(x,y)::(Integer,Char)]
+-}
 singleton :: x -> y -> T x y
 singleton x y = Node (x,y) Interval Interval
 
+{- |
+prop> \xs -> xs == Nodes.toList (Nodes.fromList (xs::[(Integer,Char)]))
+-}
 toList :: T x y -> [(x,y)]
 toList =
    let go Interval = []
        go (Node p l r) = go l ++ p : go r
    in  go
 
+{- |
+>>> Nodes.lookup (Nodes.fromList ([(0,'a'),(2::Int,'b')])) (-1)
+(Nothing,Just (0,'a'))
+>>> Nodes.lookup (Nodes.fromList ([(0,'a'),(2::Int,'b')])) 0
+(Just (0,'a'),Just (2,'b'))
+>>> Nodes.lookup (Nodes.fromList ([(0,'a'),(2::Int,'b')])) 1
+(Just (0,'a'),Just (2,'b'))
+>>> Nodes.lookup (Nodes.fromList ([(0,'a'),(2::Int,'b')])) 2
+(Just (2,'b'),Nothing)
+>>> Nodes.lookup (Nodes.fromList ([(0,'a'),(2::Int,'b')])) 3
+(Just (2,'b'),Nothing)
+>>> Nodes.lookup (Nodes.fromList ([(0,'a'),(2,'b'),(5::Int,'c')])) 3
+(Just (2,'b'),Just (5,'c'))
+-}
 lookup :: Ord x => T x y -> x -> (Maybe (x,y), Maybe (x,y))
 lookup nodes0 x0 =
    let go lb rb Interval = (lb, rb)
diff --git a/src/Numeric/Interpolation/Piece.hs b/src/Numeric/Interpolation/Piece.hs
--- a/src/Numeric/Interpolation/Piece.hs
+++ b/src/Numeric/Interpolation/Piece.hs
@@ -1,15 +1,40 @@
 module Numeric.Interpolation.Piece (
    Piece.T,
-   Piece.linear,
+   linear,
    hermite1,
    ) where
 
 import qualified Numeric.Interpolation.Private.Piece as Piece
 
 
+{- $setup
+>>> import qualified Numeric.Interpolation.Piece as Piece
+>>> import qualified Numeric.Interpolation.Private.Piece as PiecePriv
+>>> import qualified Test.QuickCheck as QC
+>>> import Test.QuickCheck ((==>))
+>>>
+>>> forAllDistinctPoints ::
+>>>    (Show a, QC.Arbitrary a, QC.Testable prop) =>
+>>>    ((Rational, a) -> (Rational, a) -> prop) -> QC.Property
+>>> forAllDistinctPoints f =
+>>>    QC.forAll QC.arbitrary $ \p1@(x1,_) ->
+>>>    QC.forAll QC.arbitrary $ \p2@(x2,_) ->
+>>>       x1/=x2  ==>  f p1 p2
+-}
+
 {- |
+prop> forAllDistinctPoints $ \p1 p2 x -> Piece.linear p1 p2 x == Piece.linear p2 p1 x
+-}
+linear :: (Fractional a) => Piece.T a a a
+linear = Piece.linear
+
+{- |
 Hermite interpolation with one derivative per node.
 That is, the interpolating polynomial is cubic.
+
+prop> forAllDistinctPoints $ \p1 p2 x -> Piece.hermite1 p1 p2 x == Piece.hermite1 p2 p1 x
+prop> forAllDistinctPoints $ \p1@(x1,y1) p2@(x2,y2) x -> Piece.linear p1 p2 x == let slope = (y2-y1)/(x2-x1) in Piece.hermite1 (x1, (y1,slope)) (x2, (y2,slope)) x
+prop> forAllDistinctPoints $ \p1 p2 x -> Piece.hermite1 p1 p2 x == PiecePriv.hermite1 p1 p2 x
 -}
 hermite1 :: (Fractional a) => Piece.T a a (a, a)
 hermite1 (x0,(y0,dy0)) (x1,(y1,dy1)) x =
diff --git a/src/Numeric/Interpolation/Piecewise.hs b/src/Numeric/Interpolation/Piecewise.hs
--- a/src/Numeric/Interpolation/Piecewise.hs
+++ b/src/Numeric/Interpolation/Piecewise.hs
@@ -7,8 +7,60 @@
 import qualified Numeric.Interpolation.Type as Type
 
 
+{- $setup
+>>> import qualified Numeric.Interpolation.Piecewise as Piecewise
+>>> import qualified Numeric.Interpolation.NodeList as Nodes
+>>> import qualified Numeric.Interpolation.Type as Type
+>>>
+>>> import qualified Data.List as List
+>>> import qualified Data.Set as Set
+>>> import Data.Array (accumArray, listArray)
+>>> import Data.List.HT (lengthAtLeast)
+>>>
+>>> import qualified Test.QuickCheck as QC
+>>> import Test.QuickCheck ((==>))
+>>>
+>>> forAllSortedRatios ::
+>>>    (QC.Testable prop) => ([Rational] -> Rational -> prop) -> QC.Property
+>>> forAllSortedRatios f =
+>>>    QC.forAll (fmap Set.toAscList QC.arbitrary) $ \nodeXs x ->
+>>>       f (map fromInteger nodeXs) (fromInteger x)
+>>>
+>>> checkEq ::
+>>>    (Ord x, Eq y, Num y) =>
+>>>    Type.T x y ny -> [x] -> x -> Bool
+>>> checkEq typ nodeXs x =
+>>>    let ys =
+>>>           map
+>>>              (flip (Piecewise.interpolateConstantExt typ) x)
+>>>              (Type.basisFunctions typ nodeXs)
+>>>        bounds = (0, length ys - 1)
+>>>    in  listArray bounds ys
+>>>        ==
+>>>        accumArray (flip const) 0 bounds
+>>>           (Type.sampleBasisFunctions typ nodeXs x)
+>>>
+>>> quantile :: (Show a, Ord a, Fractional a) => [a] -> a -> a
+>>> quantile [] _ = error "quantile: empty list"
+>>> quantile [y] _ = y
+>>> quantile ys x =
+>>>    let len = fromIntegral (length ys - 1)
+>>>    in Piecewise.interpolateConstantExt Type.linear
+>>>          (Nodes.fromList $ zip (map (/ len) $ map fromInteger [0..]) $
+>>>           List.sort ys)
+>>>          x
+-}
+
+
 {- |
 It is a checked error to interpolate outside of the range of nodes.
+
+>>> Piecewise.interpolate Type.linear (Nodes.fromList [(0,0),(3,6),(5,10::Rational)]) 2
+4 % 1
+>>> Piecewise.interpolate Type.hermite1 (Nodes.fromList [(0,(0,0)),(3,(9,6)),(5,(25,10::Rational))]) 2
+4 % 1
+>>> Piecewise.interpolate Type.hermite1 (Nodes.fromList [(0,(1,-2)),(3,(4,4)),(5,(16,8::Rational))]) 2
+1 % 1
 -}
 interpolate :: (Ord x) => Type.T x y ny -> Nodes.T x ny -> x -> y
 interpolate typ ns x =
@@ -19,6 +71,25 @@
 {- |
 Outside the range of nodes the interpolation function
 takes the value of the respective border.
+
+prop> forAllSortedRatios $ checkEq Type.linear
+prop> forAllSortedRatios $ checkEq Type.hermite1
+prop> forAllSortedRatios $ \nodeXs x -> lengthAtLeast 4 nodeXs ==> checkEq Type.cubicLinear nodeXs x
+prop> forAllSortedRatios $ \nodeXs x -> lengthAtLeast 4 nodeXs ==> checkEq Type.cubicParabola nodeXs x
+
+
+Linear interpolation can be used to compute the median, a quartile
+or any other quantile of a list of arbitrary numbers.
+
+>>> quantile [2,5,3::Rational] 0.5
+3 % 1
+>>> quantile [2,5,3,7::Rational] 0.5
+4 % 1
+>>> quantile [2,5,3,7::Rational] 0.25
+11 % 4
+
+prop> \(QC.NonEmpty xs) -> quantile (xs::[Rational]) 0 == minimum xs
+prop> \(QC.NonEmpty xs) -> quantile (xs::[Rational]) 1 == maximum xs
 -}
 interpolateConstantExt ::
    (Ord x) => Type.T x y ny -> Nodes.T x ny -> x -> y
diff --git a/src/Numeric/Interpolation/Type.hs b/src/Numeric/Interpolation/Type.hs
--- a/src/Numeric/Interpolation/Type.hs
+++ b/src/Numeric/Interpolation/Type.hs
@@ -13,6 +13,21 @@
 import Numeric.Interpolation.Private.Basis (hermite1Split)
 
 
+{- $setup
+>>> import qualified Numeric.Interpolation.Type as Type
+>>>
+>>> checkOverlap :: Type.T Double y ny -> [Double] -> Double -> Bool
+>>> checkOverlap typ xs xi =
+>>>    let samples = map fst $ Type.sampleBasisFunctions typ xs xi
+>>>    in  all (< minimum samples + Type.basisOverlap typ) samples
+>>>
+>>> checkOverlapNotTotal :: Type.T Double y ny -> [Double] -> Double -> Bool
+>>> checkOverlapNotTotal typ xs xi =
+>>>    let samples = map fst $ Type.sampleBasisFunctions typ xs xi
+>>>    in  maximum samples - minimum samples < Type.basisOverlap typ
+-}
+
+
 data T x y ny =
    Cons {
       ssvFromNodes :: [x] -> [y] -> String,
@@ -27,6 +42,9 @@
       valueFromNode :: ny -> y
    }
 
+{- |
+prop> checkOverlap Type.linear
+-}
 linear :: (Fractional a, Ord a, Show a) => T a a a
 linear =
    Cons {
@@ -40,6 +58,9 @@
       valueFromNode = id
    }
 
+{- |
+prop> checkOverlap Type.hermite1
+-}
 hermite1 :: (Fractional a, Ord a, Show a) => T a a (a, a)
 hermite1 =
    Cons {
@@ -56,6 +77,9 @@
       valueFromNode = fst
    }
 
+{- |
+prop> checkOverlap Type.cubicLinear
+-}
 cubicLinear :: (Fractional a, Ord a, Show a) => T a a (a, a)
 cubicLinear =
    Cons {
@@ -69,6 +93,9 @@
       valueFromNode = fst
    }
 
+{- |
+prop> checkOverlap Type.cubicParabola
+-}
 cubicParabola :: (Fractional a, Ord a, Show a) => T a a (a, a)
 cubicParabola =
    Cons {
diff --git a/test-module.list b/test-module.list
new file mode 100644
--- /dev/null
+++ b/test-module.list
@@ -0,0 +1,4 @@
+Numeric.Interpolation.Type
+Numeric.Interpolation.NodeList
+Numeric.Interpolation.Piece
+Numeric.Interpolation.Piecewise
diff --git a/test/Test.hs b/test/Test.hs
--- a/test/Test.hs
+++ b/test/Test.hs
@@ -1,16 +1,16 @@
+-- Do not edit! Automatically created with doctest-extract.
 module Main where
 
-import qualified Test.Piece as Piece
-import qualified Test.Sample as Sample
-import qualified Test.Overlap as Overlap
-
+import qualified Test.Numeric.Interpolation.Type
+import qualified Test.Numeric.Interpolation.NodeList
+import qualified Test.Numeric.Interpolation.Piece
+import qualified Test.Numeric.Interpolation.Piecewise
 
-run :: String -> [(String, IO ())] -> IO ()
-run prefix =
-   mapM_ (\(msg,act) -> putStr (prefix ++ '.' : msg ++ ": ") >> act)
+import qualified Test.DocTest.Driver as DocTest
 
 main :: IO ()
-main = do
-   run "Piece" Piece.tests
-   run "Sample" Sample.tests
-   run "Overlap" Overlap.tests
+main = DocTest.run $ do
+    Test.Numeric.Interpolation.Type.test
+    Test.Numeric.Interpolation.NodeList.test
+    Test.Numeric.Interpolation.Piece.test
+    Test.Numeric.Interpolation.Piecewise.test
diff --git a/test/Test/Numeric/Interpolation/NodeList.hs b/test/Test/Numeric/Interpolation/NodeList.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Numeric/Interpolation/NodeList.hs
@@ -0,0 +1,79 @@
+-- Do not edit! Automatically created with doctest-extract from src/Numeric/Interpolation/NodeList.hs
+{-# LINE 19 "src/Numeric/Interpolation/NodeList.hs" #-}
+
+module Test.Numeric.Interpolation.NodeList where
+
+import Test.DocTest.Base
+import qualified Test.DocTest.Driver as DocTest
+
+{-# LINE 20 "src/Numeric/Interpolation/NodeList.hs" #-}
+import     qualified Numeric.Interpolation.NodeList as Nodes
+import     qualified Data.Traversable as Trav
+import     qualified Data.Foldable as Fold
+import     qualified Data.List as List
+import     Data.Tuple.HT (mapSnd)
+import     Data.Char (ord)
+
+test :: DocTest.T ()
+test = do
+ DocTest.printPrefix "Numeric.Interpolation.NodeList:33: "
+{-# LINE 33 "src/Numeric/Interpolation/NodeList.hs" #-}
+ DocTest.property
+{-# LINE 33 "src/Numeric/Interpolation/NodeList.hs" #-}
+     (\xs -> map (mapSnd ord) xs == Nodes.toList (fmap ord (Nodes.fromList (xs::[(Integer,Char)]))))
+ DocTest.printPrefix "Numeric.Interpolation.NodeList:42: "
+{-# LINE 42 "src/Numeric/Interpolation/NodeList.hs" #-}
+ DocTest.property
+{-# LINE 42 "src/Numeric/Interpolation/NodeList.hs" #-}
+     (\xs -> map snd xs == Fold.toList (Nodes.fromList (xs::[(Integer,Char)])))
+ DocTest.printPrefix "Numeric.Interpolation.NodeList:51: "
+{-# LINE 51 "src/Numeric/Interpolation/NodeList.hs" #-}
+ DocTest.property
+{-# LINE 51 "src/Numeric/Interpolation/NodeList.hs" #-}
+     (\x xs -> let f acc y = (acc+y,acc) in List.mapAccumL f x (map snd xs) == mapSnd Fold.toList (Trav.mapAccumL f x (Nodes.fromList (xs::[(Int,Integer)]))))
+ DocTest.printPrefix "Numeric.Interpolation.NodeList:77: "
+{-# LINE 77 "src/Numeric/Interpolation/NodeList.hs" #-}
+ DocTest.property
+{-# LINE 77 "src/Numeric/Interpolation/NodeList.hs" #-}
+     (\x y -> Nodes.singleton x y == Nodes.fromList [(x,y)::(Integer,Char)])
+ DocTest.printPrefix "Numeric.Interpolation.NodeList:83: "
+{-# LINE 83 "src/Numeric/Interpolation/NodeList.hs" #-}
+ DocTest.property
+{-# LINE 83 "src/Numeric/Interpolation/NodeList.hs" #-}
+     (\xs -> xs == Nodes.toList (Nodes.fromList (xs::[(Integer,Char)])))
+ DocTest.printPrefix "Numeric.Interpolation.NodeList:92: "
+{-# LINE 92 "src/Numeric/Interpolation/NodeList.hs" #-}
+ DocTest.example
+{-# LINE 92 "src/Numeric/Interpolation/NodeList.hs" #-}
+   (Nodes.lookup (Nodes.fromList ([(0,'a'),(2::Int,'b')])) (-1))
+  [ExpectedLine [LineChunk "(Nothing,Just (0,'a'))"]]
+ DocTest.printPrefix "Numeric.Interpolation.NodeList:94: "
+{-# LINE 94 "src/Numeric/Interpolation/NodeList.hs" #-}
+ DocTest.example
+{-# LINE 94 "src/Numeric/Interpolation/NodeList.hs" #-}
+   (Nodes.lookup (Nodes.fromList ([(0,'a'),(2::Int,'b')])) 0)
+  [ExpectedLine [LineChunk "(Just (0,'a'),Just (2,'b'))"]]
+ DocTest.printPrefix "Numeric.Interpolation.NodeList:96: "
+{-# LINE 96 "src/Numeric/Interpolation/NodeList.hs" #-}
+ DocTest.example
+{-# LINE 96 "src/Numeric/Interpolation/NodeList.hs" #-}
+   (Nodes.lookup (Nodes.fromList ([(0,'a'),(2::Int,'b')])) 1)
+  [ExpectedLine [LineChunk "(Just (0,'a'),Just (2,'b'))"]]
+ DocTest.printPrefix "Numeric.Interpolation.NodeList:98: "
+{-# LINE 98 "src/Numeric/Interpolation/NodeList.hs" #-}
+ DocTest.example
+{-# LINE 98 "src/Numeric/Interpolation/NodeList.hs" #-}
+   (Nodes.lookup (Nodes.fromList ([(0,'a'),(2::Int,'b')])) 2)
+  [ExpectedLine [LineChunk "(Just (2,'b'),Nothing)"]]
+ DocTest.printPrefix "Numeric.Interpolation.NodeList:100: "
+{-# LINE 100 "src/Numeric/Interpolation/NodeList.hs" #-}
+ DocTest.example
+{-# LINE 100 "src/Numeric/Interpolation/NodeList.hs" #-}
+   (Nodes.lookup (Nodes.fromList ([(0,'a'),(2::Int,'b')])) 3)
+  [ExpectedLine [LineChunk "(Just (2,'b'),Nothing)"]]
+ DocTest.printPrefix "Numeric.Interpolation.NodeList:102: "
+{-# LINE 102 "src/Numeric/Interpolation/NodeList.hs" #-}
+ DocTest.example
+{-# LINE 102 "src/Numeric/Interpolation/NodeList.hs" #-}
+   (Nodes.lookup (Nodes.fromList ([(0,'a'),(2,'b'),(5::Int,'c')])) 3)
+  [ExpectedLine [LineChunk "(Just (2,'b'),Just (5,'c'))"]]
diff --git a/test/Test/Numeric/Interpolation/Piece.hs b/test/Test/Numeric/Interpolation/Piece.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Numeric/Interpolation/Piece.hs
@@ -0,0 +1,43 @@
+-- Do not edit! Automatically created with doctest-extract from src/Numeric/Interpolation/Piece.hs
+{-# LINE 10 "src/Numeric/Interpolation/Piece.hs" #-}
+
+module Test.Numeric.Interpolation.Piece where
+
+import qualified Test.DocTest.Driver as DocTest
+
+{-# LINE 11 "src/Numeric/Interpolation/Piece.hs" #-}
+import     qualified Numeric.Interpolation.Piece as Piece
+import     qualified Numeric.Interpolation.Private.Piece as PiecePriv
+import     qualified Test.QuickCheck as QC
+import     Test.QuickCheck ((==>))
+
+forAllDistinctPoints     ::
+       (Show a, QC.Arbitrary a, QC.Testable prop) =>
+       ((Rational, a) -> (Rational, a) -> prop) -> QC.Property
+forAllDistinctPoints     f =
+       QC.forAll QC.arbitrary $ \p1@(x1,_) ->
+       QC.forAll QC.arbitrary $ \p2@(x2,_) ->
+          x1/=x2  ==>  f p1 p2
+
+test :: DocTest.T ()
+test = do
+ DocTest.printPrefix "Numeric.Interpolation.Piece:26: "
+{-# LINE 26 "src/Numeric/Interpolation/Piece.hs" #-}
+ DocTest.property
+{-# LINE 26 "src/Numeric/Interpolation/Piece.hs" #-}
+     (forAllDistinctPoints $ \p1 p2 x -> Piece.linear p1 p2 x == Piece.linear p2 p1 x)
+ DocTest.printPrefix "Numeric.Interpolation.Piece:35: "
+{-# LINE 35 "src/Numeric/Interpolation/Piece.hs" #-}
+ DocTest.property
+{-# LINE 35 "src/Numeric/Interpolation/Piece.hs" #-}
+     (forAllDistinctPoints $ \p1 p2 x -> Piece.hermite1 p1 p2 x == Piece.hermite1 p2 p1 x)
+ DocTest.printPrefix "Numeric.Interpolation.Piece:36: "
+{-# LINE 36 "src/Numeric/Interpolation/Piece.hs" #-}
+ DocTest.property
+{-# LINE 36 "src/Numeric/Interpolation/Piece.hs" #-}
+     (forAllDistinctPoints $ \p1@(x1,y1) p2@(x2,y2) x -> Piece.linear p1 p2 x == let slope = (y2-y1)/(x2-x1) in Piece.hermite1 (x1, (y1,slope)) (x2, (y2,slope)) x)
+ DocTest.printPrefix "Numeric.Interpolation.Piece:37: "
+{-# LINE 37 "src/Numeric/Interpolation/Piece.hs" #-}
+ DocTest.property
+{-# LINE 37 "src/Numeric/Interpolation/Piece.hs" #-}
+     (forAllDistinctPoints $ \p1 p2 x -> Piece.hermite1 p1 p2 x == PiecePriv.hermite1 p1 p2 x)
diff --git a/test/Test/Numeric/Interpolation/Piecewise.hs b/test/Test/Numeric/Interpolation/Piecewise.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Numeric/Interpolation/Piecewise.hs
@@ -0,0 +1,119 @@
+-- Do not edit! Automatically created with doctest-extract from src/Numeric/Interpolation/Piecewise.hs
+{-# LINE 10 "src/Numeric/Interpolation/Piecewise.hs" #-}
+
+module Test.Numeric.Interpolation.Piecewise where
+
+import Test.DocTest.Base
+import qualified Test.DocTest.Driver as DocTest
+
+{-# LINE 11 "src/Numeric/Interpolation/Piecewise.hs" #-}
+import     qualified Numeric.Interpolation.Piecewise as Piecewise
+import     qualified Numeric.Interpolation.NodeList as Nodes
+import     qualified Numeric.Interpolation.Type as Type
+
+import     qualified Data.List as List
+import     qualified Data.Set as Set
+import     Data.Array (accumArray, listArray)
+import     Data.List.HT (lengthAtLeast)
+
+import     qualified Test.QuickCheck as QC
+import     Test.QuickCheck ((==>))
+
+forAllSortedRatios     ::
+       (QC.Testable prop) => ([Rational] -> Rational -> prop) -> QC.Property
+forAllSortedRatios     f =
+       QC.forAll (fmap Set.toAscList QC.arbitrary) $ \nodeXs x ->
+          f (map fromInteger nodeXs) (fromInteger x)
+
+checkEq     ::
+       (Ord x, Eq y, Num y) =>
+       Type.T x y ny -> [x] -> x -> Bool
+checkEq     typ nodeXs x =
+       let ys =
+              map
+                 (flip (Piecewise.interpolateConstantExt typ) x)
+                 (Type.basisFunctions typ nodeXs)
+           bounds = (0, length ys - 1)
+       in  listArray bounds ys
+           ==
+           accumArray (flip const) 0 bounds
+              (Type.sampleBasisFunctions typ nodeXs x)
+
+quantile     :: (Show a, Ord a, Fractional a) => [a] -> a -> a
+quantile     [] _ = error "quantile: empty list"
+quantile     [y] _ = y
+quantile     ys x =
+       let len = fromIntegral (length ys - 1)
+       in Piecewise.interpolateConstantExt Type.linear
+             (Nodes.fromList $ zip (map (/ len) $ map fromInteger [0..]) $
+              List.sort ys)
+             x
+
+test :: DocTest.T ()
+test = do
+ DocTest.printPrefix "Numeric.Interpolation.Piecewise:58: "
+{-# LINE 58 "src/Numeric/Interpolation/Piecewise.hs" #-}
+ DocTest.example
+{-# LINE 58 "src/Numeric/Interpolation/Piecewise.hs" #-}
+   (Piecewise.interpolate Type.linear (Nodes.fromList [(0,0),(3,6),(5,10::Rational)]) 2)
+  [ExpectedLine [LineChunk "4 % 1"]]
+ DocTest.printPrefix "Numeric.Interpolation.Piecewise:60: "
+{-# LINE 60 "src/Numeric/Interpolation/Piecewise.hs" #-}
+ DocTest.example
+{-# LINE 60 "src/Numeric/Interpolation/Piecewise.hs" #-}
+   (Piecewise.interpolate Type.hermite1 (Nodes.fromList [(0,(0,0)),(3,(9,6)),(5,(25,10::Rational))]) 2)
+  [ExpectedLine [LineChunk "4 % 1"]]
+ DocTest.printPrefix "Numeric.Interpolation.Piecewise:62: "
+{-# LINE 62 "src/Numeric/Interpolation/Piecewise.hs" #-}
+ DocTest.example
+{-# LINE 62 "src/Numeric/Interpolation/Piecewise.hs" #-}
+   (Piecewise.interpolate Type.hermite1 (Nodes.fromList [(0,(1,-2)),(3,(4,4)),(5,(16,8::Rational))]) 2)
+  [ExpectedLine [LineChunk "1 % 1"]]
+ DocTest.printPrefix "Numeric.Interpolation.Piecewise:75: "
+{-# LINE 75 "src/Numeric/Interpolation/Piecewise.hs" #-}
+ DocTest.property
+{-# LINE 75 "src/Numeric/Interpolation/Piecewise.hs" #-}
+     (forAllSortedRatios $ checkEq Type.linear)
+ DocTest.printPrefix "Numeric.Interpolation.Piecewise:76: "
+{-# LINE 76 "src/Numeric/Interpolation/Piecewise.hs" #-}
+ DocTest.property
+{-# LINE 76 "src/Numeric/Interpolation/Piecewise.hs" #-}
+     (forAllSortedRatios $ checkEq Type.hermite1)
+ DocTest.printPrefix "Numeric.Interpolation.Piecewise:77: "
+{-# LINE 77 "src/Numeric/Interpolation/Piecewise.hs" #-}
+ DocTest.property
+{-# LINE 77 "src/Numeric/Interpolation/Piecewise.hs" #-}
+     (forAllSortedRatios $ \nodeXs x -> lengthAtLeast 4 nodeXs ==> checkEq Type.cubicLinear nodeXs x)
+ DocTest.printPrefix "Numeric.Interpolation.Piecewise:78: "
+{-# LINE 78 "src/Numeric/Interpolation/Piecewise.hs" #-}
+ DocTest.property
+{-# LINE 78 "src/Numeric/Interpolation/Piecewise.hs" #-}
+     (forAllSortedRatios $ \nodeXs x -> lengthAtLeast 4 nodeXs ==> checkEq Type.cubicParabola nodeXs x)
+ DocTest.printPrefix "Numeric.Interpolation.Piecewise:91: "
+{-# LINE 91 "src/Numeric/Interpolation/Piecewise.hs" #-}
+ DocTest.property
+{-# LINE 91 "src/Numeric/Interpolation/Piecewise.hs" #-}
+     (\(QC.NonEmpty xs) -> quantile (xs::[Rational]) 0 == minimum xs)
+ DocTest.printPrefix "Numeric.Interpolation.Piecewise:92: "
+{-# LINE 92 "src/Numeric/Interpolation/Piecewise.hs" #-}
+ DocTest.property
+{-# LINE 92 "src/Numeric/Interpolation/Piecewise.hs" #-}
+     (\(QC.NonEmpty xs) -> quantile (xs::[Rational]) 1 == maximum xs)
+ DocTest.printPrefix "Numeric.Interpolation.Piecewise:84: "
+{-# LINE 84 "src/Numeric/Interpolation/Piecewise.hs" #-}
+ DocTest.example
+{-# LINE 84 "src/Numeric/Interpolation/Piecewise.hs" #-}
+   (quantile [2,5,3::Rational] 0.5)
+  [ExpectedLine [LineChunk "3 % 1"]]
+ DocTest.printPrefix "Numeric.Interpolation.Piecewise:86: "
+{-# LINE 86 "src/Numeric/Interpolation/Piecewise.hs" #-}
+ DocTest.example
+{-# LINE 86 "src/Numeric/Interpolation/Piecewise.hs" #-}
+   (quantile [2,5,3,7::Rational] 0.5)
+  [ExpectedLine [LineChunk "4 % 1"]]
+ DocTest.printPrefix "Numeric.Interpolation.Piecewise:88: "
+{-# LINE 88 "src/Numeric/Interpolation/Piecewise.hs" #-}
+ DocTest.example
+{-# LINE 88 "src/Numeric/Interpolation/Piecewise.hs" #-}
+   (quantile [2,5,3,7::Rational] 0.25)
+  [ExpectedLine [LineChunk "11 % 4"]]
diff --git a/test/Test/Numeric/Interpolation/Type.hs b/test/Test/Numeric/Interpolation/Type.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Numeric/Interpolation/Type.hs
@@ -0,0 +1,42 @@
+-- Do not edit! Automatically created with doctest-extract from src/Numeric/Interpolation/Type.hs
+{-# LINE 16 "src/Numeric/Interpolation/Type.hs" #-}
+
+module Test.Numeric.Interpolation.Type where
+
+import qualified Test.DocTest.Driver as DocTest
+
+{-# LINE 17 "src/Numeric/Interpolation/Type.hs" #-}
+import     qualified Numeric.Interpolation.Type as Type
+
+checkOverlap     :: Type.T Double y ny -> [Double] -> Double -> Bool
+checkOverlap     typ xs xi =
+       let samples = map fst $ Type.sampleBasisFunctions typ xs xi
+       in  all (< minimum samples + Type.basisOverlap typ) samples
+
+checkOverlapNotTotal     :: Type.T Double y ny -> [Double] -> Double -> Bool
+checkOverlapNotTotal     typ xs xi =
+       let samples = map fst $ Type.sampleBasisFunctions typ xs xi
+       in  maximum samples - minimum samples < Type.basisOverlap typ
+
+test :: DocTest.T ()
+test = do
+ DocTest.printPrefix "Numeric.Interpolation.Type:46: "
+{-# LINE 46 "src/Numeric/Interpolation/Type.hs" #-}
+ DocTest.property
+{-# LINE 46 "src/Numeric/Interpolation/Type.hs" #-}
+     (checkOverlap Type.linear)
+ DocTest.printPrefix "Numeric.Interpolation.Type:62: "
+{-# LINE 62 "src/Numeric/Interpolation/Type.hs" #-}
+ DocTest.property
+{-# LINE 62 "src/Numeric/Interpolation/Type.hs" #-}
+     (checkOverlap Type.hermite1)
+ DocTest.printPrefix "Numeric.Interpolation.Type:81: "
+{-# LINE 81 "src/Numeric/Interpolation/Type.hs" #-}
+ DocTest.property
+{-# LINE 81 "src/Numeric/Interpolation/Type.hs" #-}
+     (checkOverlap Type.cubicLinear)
+ DocTest.printPrefix "Numeric.Interpolation.Type:97: "
+{-# LINE 97 "src/Numeric/Interpolation/Type.hs" #-}
+ DocTest.property
+{-# LINE 97 "src/Numeric/Interpolation/Type.hs" #-}
+     (checkOverlap Type.cubicParabola)
diff --git a/test/Test/Overlap.hs b/test/Test/Overlap.hs
deleted file mode 100644
--- a/test/Test/Overlap.hs
+++ /dev/null
@@ -1,25 +0,0 @@
-module Test.Overlap where
-
-import qualified Numeric.Interpolation.Type as Type
-
-import Test.QuickCheck (quickCheck, )
-
-
-
-test :: Type.T Double y ny -> IO ()
-test typ =
-   quickCheck $ \xs xi ->
-      let samples = map fst $ Type.sampleBasisFunctions typ xs xi
-          {- not total:
-          maximum samples - minimum samples < Type.basisOverlap typ
-          -}
-      in  all (< minimum samples + Type.basisOverlap typ) samples
-
-
-tests :: [(String, IO ())]
-tests =
-   ("linear", test Type.linear) :
-   ("hermite1", test Type.hermite1) :
-   ("cubicLinear", test Type.cubicLinear) :
-   ("cubicParabola", test Type.cubicParabola) :
-   []
diff --git a/test/Test/Piece.hs b/test/Test/Piece.hs
deleted file mode 100644
--- a/test/Test/Piece.hs
+++ /dev/null
@@ -1,60 +0,0 @@
-module Test.Piece where
-
-import qualified Numeric.Interpolation.Piece as Piece
-import qualified Numeric.Interpolation.Private.Piece as PiecePriv
-
-import Test.QuickCheck (Property, quickCheck, (==>), )
-
-
-type Point = (Rational, Rational)
-
-linearCommutative ::
-   Point -> Point -> Rational -> Property
-linearCommutative p1@(x1,_) p2@(x2,_) x =
-   x1/=x2
-   ==>
-   Piece.linear p1 p2 x
-   ==
-   Piece.linear p2 p1 x
-
-
-type PointSlope = (Rational, (Rational, Rational))
-
-hermite1Commutative ::
-   PointSlope -> PointSlope -> Rational -> Property
-hermite1Commutative p1@(x1,_) p2@(x2,_) x =
-   x1/=x2
-   ==>
-   Piece.hermite1 p1 p2 x
-   ==
-   Piece.hermite1 p2 p1 x
-
-
-linearHermite1 ::
-   Point -> Point -> Rational -> Property
-linearHermite1 p1@(x1,y1) p2@(x2,y2) x =
-   x1/=x2
-   ==>
-   Piece.linear p1 p2 x
-   ==
-   let slope = (y2-y1)/(x2-x1)
-   in  Piece.hermite1 (x1, (y1,slope)) (x2, (y2, slope)) x
-
-
-hermite1Alternative ::
-   PointSlope -> PointSlope -> Rational -> Property
-hermite1Alternative p1@(x1,_) p2@(x2,_) x =
-   x1/=x2
-   ==>
-   Piece.hermite1 p1 p2 x
-   ==
-   PiecePriv.hermite1 p1 p2 x
-
-
-tests :: [(String, IO ())]
-tests =
-   ("linearCommutative", quickCheck linearCommutative) :
-   ("hermite1Commutative", quickCheck hermite1Commutative) :
-   ("linearHermite1", quickCheck linearHermite1) :
-   ("hermite1Alternative", quickCheck hermite1Alternative) :
-   []
diff --git a/test/Test/Sample.hs b/test/Test/Sample.hs
deleted file mode 100644
--- a/test/Test/Sample.hs
+++ /dev/null
@@ -1,62 +0,0 @@
-module Test.Sample where
-
-import qualified Numeric.Interpolation.Type as Type
-import qualified Numeric.Interpolation.Piecewise as Piecewise
-
-import qualified Data.Set as Set
-import Data.Array (accumArray, listArray, )
-import Data.List.HT (lengthAtLeast, )
-
-import Test.QuickCheck (Property, quickCheck, (==>), )
-
-
-
-withSortedRatios ::
-   ([Rational] -> Rational -> a) ->
-   ([Integer] -> Integer -> a)
-withSortedRatios f nodeXs x =
-   f (map fromInteger $ Set.toAscList $ Set.fromList nodeXs) (fromInteger x)
-
-checkEq ::
-   (Ord x, Eq y, Num y) =>
-   Type.T x y ny -> [x] -> x -> Bool
-checkEq typ nodeXs x =
-   let ys =
-          map
-             (flip (Piecewise.interpolateConstantExt typ) x)
-             (Type.basisFunctions typ nodeXs)
-       bounds = (0, length ys - 1)
-   in  listArray bounds ys
-       ==
-       accumArray (flip const) 0 bounds
-          (Type.sampleBasisFunctions typ nodeXs x)
-
-
-linear :: [Integer] -> Integer -> Bool
-linear = withSortedRatios $ checkEq Type.linear
-
-hermite1 :: [Integer] -> Integer -> Bool
-hermite1 = withSortedRatios $ checkEq Type.hermite1
-
-
-derivativeFree ::
-   Type.T Rational Rational ny ->
-   [Integer] -> Integer -> Property
-derivativeFree typ =
-   withSortedRatios $ \nodeXs x ->
-      lengthAtLeast 4 nodeXs ==> checkEq typ nodeXs x
-
-cubicLinear :: [Integer] -> Integer -> Property
-cubicLinear = derivativeFree Type.cubicLinear
-
-cubicParabola :: [Integer] -> Integer -> Property
-cubicParabola = derivativeFree Type.cubicParabola
-
-
-tests :: [(String, IO ())]
-tests =
-   ("linear", quickCheck linear) :
-   ("hermite1", quickCheck hermite1) :
-   ("cubicLinear", quickCheck cubicLinear) :
-   ("cubicParabola", quickCheck cubicParabola) :
-   []
