diff --git a/LICENCE b/LICENCE
--- a/LICENCE
+++ b/LICENCE
@@ -1,4 +1,5 @@
 Copyright 2013-2016 NICTA Limited
+Copyright 2018, Commonwealth Scientific and Industrial Research Organisation (CSIRO) ABN 41 687 119 230.
 
 All rights reserved.
 
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/Setup.lhs b/Setup.lhs
deleted file mode 100644
--- a/Setup.lhs
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env runhaskell
-\begin{code}
-{-# OPTIONS_GHC -Wall #-}
-module Main (main) where
-
-import Data.List ( nub )
-import Data.Version ( showVersion )
-import Distribution.Package ( PackageName(PackageName), PackageId, InstalledPackageId, packageVersion, packageName )
-import Distribution.PackageDescription ( PackageDescription(), TestSuite(..) )
-import Distribution.Simple ( defaultMainWithHooks, UserHooks(..), simpleUserHooks )
-import Distribution.Simple.Utils ( rewriteFile, createDirectoryIfMissingVerbose )
-import Distribution.Simple.BuildPaths ( autogenModulesDir )
-import Distribution.Simple.Setup ( BuildFlags(buildVerbosity), fromFlag )
-import Distribution.Simple.LocalBuildInfo ( withLibLBI, withTestLBI, LocalBuildInfo(), ComponentLocalBuildInfo(componentPackageDeps) )
-import Distribution.Verbosity ( Verbosity )
-import System.FilePath ( (</>) )
-
-main :: IO ()
-main = defaultMainWithHooks simpleUserHooks
-  { buildHook = \pkg lbi hooks flags -> do
-     generateBuildModule (fromFlag (buildVerbosity flags)) pkg lbi
-     buildHook simpleUserHooks pkg lbi hooks flags
-  }
-
-generateBuildModule :: Verbosity -> PackageDescription -> LocalBuildInfo -> IO ()
-generateBuildModule verbosity pkg lbi = do
-  let dir = autogenModulesDir lbi
-  createDirectoryIfMissingVerbose verbosity True dir
-  withLibLBI pkg lbi $ \_ libcfg -> do
-    withTestLBI pkg lbi $ \suite suitecfg -> do
-      rewriteFile (dir </> "Build_" ++ testName suite ++ ".hs") $ unlines
-        [ "module Build_" ++ testName suite ++ " where"
-        , "deps :: [String]"
-        , "deps = " ++ (show $ formatdeps (testDeps libcfg suitecfg))
-        ]
-  where
-    formatdeps = map (formatone . snd)
-    formatone p = case packageName p of
-      PackageName n -> n ++ "-" ++ showVersion (packageVersion p)
-
-testDeps :: ComponentLocalBuildInfo -> ComponentLocalBuildInfo -> [(InstalledPackageId, PackageId)]
-testDeps xs ys = nub $ componentPackageDeps xs ++ componentPackageDeps ys
-
-\end{code}
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,8 @@
+0.2
+
+* Depend on papa
+* Support GHC 8.4
+
 0.1.2
 
 * Functions to construct using degrees.
diff --git a/coordinate.cabal b/coordinate.cabal
--- a/coordinate.cabal
+++ b/coordinate.cabal
@@ -1,28 +1,28 @@
 name:               coordinate
-version:            0.1.2
+version:            0.2
 license:            BSD3
 license-file:       LICENCE
 author:             Tony Morris <ʇǝu˙sıɹɹoɯʇ@ןןǝʞsɐɥ>
 maintainer:         Tony Morris
 copyright:          Copyright (C) 2013-2016 NICTA Limited
+                    Copyright (c) 2018, Commonwealth Scientific and Industrial Research Organisation (CSIRO) ABN 41 687 119 230.
+
 synopsis:           A representation of latitude and longitude
 category:           Development
 description:       
-  <<http://i.imgur.com/Ns5hntl.jpg>>
+  <<http://i.imgur.com/uZnp9ke.png>>
   .
   A representation of latitude and longitude
-homepage:           https://github.com/NICTA/coordinate
-bug-reports:        https://github.com/NICTA/coordinate/issues
+homepage:           https://github.com/qfpl/coordinate
+bug-reports:        https://github.com/qfpl/coordinate/issues
 cabal-version:      >= 1.10
-build-type:         Custom
+build-type:         Simple
 extra-source-files: changelog.md, other-licence.md
+tested-with:        GHC == 8.4.1, GHC == 8.2.2, GHC == 8.0.2, GHC == 7.10.3
 
 source-repository   head
   type:             git
-  location:         git@github.com:NICTA/coordinate.git
-
-flag                small_base
-  description:      Choose the new, split-up base package.
+  location:         git@github.com:qfpl/coordinate.git
 
 library
   default-language:
@@ -30,8 +30,9 @@
 
   build-depends:
                       base >= 4 && < 5
-                    , lens >= 4.0 && < 5.0
+                    , lens >= 4 && < 5
                     , transformers >= 0.4 && < 0.6
+                    , papa >= 0.3 && < 0.4
                     
   ghc-options:
                     -Wall
@@ -53,23 +54,21 @@
                     Data.Geodetic.Sphere
                     Data.Geodetic.XY
 
-test-suite doctests
+test-suite hunit
   type:
                     exitcode-stdio-1.0
 
   main-is:
-                    doctests.hs
+                    hunit_tests.hs
 
   default-language:
                     Haskell2010
 
   build-depends:
-                      base < 5 && >= 3
-                    , doctest >= 0.9.7
-                    , filepath >= 1.3
-                    , directory >= 1.1
-                    , QuickCheck >= 2.0
-                    , template-haskell >= 2.8
+                      base >= 3 && < 5
+                      , coordinate
+                      , HUnit >= 1.2 && < 1.7
+                      , lens >= 4 && < 5
 
   ghc-options:
                     -Wall
diff --git a/src/Data/Geodetic/ECEF.hs b/src/Data/Geodetic/ECEF.hs
--- a/src/Data/Geodetic/ECEF.hs
+++ b/src/Data/Geodetic/ECEF.hs
@@ -6,14 +6,9 @@
 , HasECEF(..)
 ) where
 
-import Control.Applicative(Applicative((<*>)))
-import Control.Lens(makeClassy, lens)
-import Data.Eq(Eq)
-import Data.Functor((<$>))
 import Data.Geodetic.HasDoubles(HasDoubles(doubles))
 import Data.Geodetic.XY(XY, HasXY(xY))
-import Data.Ord(Ord)
-import Prelude(Show, Double)
+import Papa
 
 data ECEF =
   ECEF {
diff --git a/src/Data/Geodetic/Ellipsoid.hs b/src/Data/Geodetic/Ellipsoid.hs
--- a/src/Data/Geodetic/Ellipsoid.hs
+++ b/src/Data/Geodetic/Ellipsoid.hs
@@ -23,14 +23,8 @@
 , clarke1880
 ) where
 
-import Control.Applicative(Applicative((<*>)))
-import Control.Category((.))
-import Control.Lens(makeClassy, Lens', involuted)
-import Data.Eq(Eq)
-import Data.Functor((<$>))
 import Data.Geodetic.HasDoubles(HasDoubles(doubles))
-import Data.Ord(Ord)
-import Prelude(Show, Double, (/))
+import Papa
 
 data Ellipsoid =
   Ellipsoid {
diff --git a/src/Data/Geodetic/EllipsoidReaderT.hs b/src/Data/Geodetic/EllipsoidReaderT.hs
--- a/src/Data/Geodetic/EllipsoidReaderT.hs
+++ b/src/Data/Geodetic/EllipsoidReaderT.hs
@@ -25,28 +25,21 @@
 , earthGeo
 ) where
 
-import Control.Category((.))
-import Control.Applicative(Applicative((<*>), pure), liftA2, Alternative((<|>), empty))
-import Control.Lens(makeWrapped, (#), _Unwrapped, ReifiedIso', ReifiedIso(Iso), Iso', iso, from, (^.), (&), Wrapped(_Wrapped'))
-import Control.Monad(Monad((>>=), return), MonadPlus(mzero, mplus))
+import Control.Applicative(Alternative((<|>), empty), liftA2)
+import qualified Control.Monad as Monad(return, (>>=))
+import Control.Monad(MonadPlus(mzero, mplus))
 import Control.Monad.Fix(MonadFix(mfix))
 import Control.Monad.IO.Class(MonadIO(liftIO))
 import Control.Monad.Trans.Class(MonadTrans(lift))
 import Control.Monad.Trans.Reader(ReaderT)
 import Control.Monad.Zip(MonadZip(mzip))
-import Data.Functor(Functor(fmap), (<$>))
 import Data.Functor.Identity(Identity(Identity, runIdentity))
 import Data.Geodetic.ECEF(ECEF(..), HasECEF(z))
 import Data.Geodetic.Ellipsoid(Ellipsoid, HasEllipsoid(semiMajor, flattening), flatteningReciprocal, wgs84)
 import Data.Geodetic.LL(LL(LL), HasLL(lat, lon))
 import Data.Geodetic.LLH(LLH(LLH), HasLLH(height))
 import Data.Geodetic.XY(XY(XY), HasXY(x, y))
-import Data.Int(Int)
-import Prelude(Double, Num((*), (+), (-)), Fractional((/)), Floating(sin, cos, sqrt, atan, (**)), RealFloat(atan2), (^))
-
--- $setup
--- >>> import Control.Lens(ReifiedIso(runIso))
--- >>> import Data.Geodetic.Ellipsoid
+import Papa
 
 newtype EllipsoidReaderT f a =
   EllipsoidReaderT (Ellipsoid -> f a)
@@ -98,9 +91,9 @@
 
 instance Monad f => Monad (EllipsoidReaderT f) where
   return =
-    EllipsoidReaderT . return . return
+    EllipsoidReaderT . Monad.return . Monad.return
   EllipsoidReaderT k >>= f =
-    EllipsoidReaderT (\e -> k e >>= \q -> e & f q ^. _Wrapped')
+    EllipsoidReaderT (\e -> k e Monad.>>= \q -> e & f q ^. _Wrapped')
 
 instance Alternative f => Alternative (EllipsoidReaderT f) where
   empty =
@@ -162,20 +155,12 @@
   readFlatteningReciprocal <*>
   readSemiMajor
 
--- |
---
--- >>> wgs84' eccentricitySquared
--- 6.6943799901413165e-3
 eccentricitySquared ::
   Applicative f =>
   EllipsoidReaderT f Double
 eccentricitySquared =
   (\f -> 2 * f - (f * f)) <$> readFlatteningReciprocal
 
--- |
---
--- >>> wgs84' eccentricitySquared'
--- 6.694455244784511e-3
 eccentricitySquared' ::
   Applicative f => 
   EllipsoidReaderT f Double
@@ -189,19 +174,6 @@
 distributeNormal t =
   (\k -> k t) <$> normal
 
--- |
---
--- >>> wgs84' normal 7
--- 6387371.845852088
---
--- >>> wgs84' normal 71
--- 6397535.266650572
---
--- >>> wgs84' normal 711
--- 6393308.675975408
---
--- >>> wgs84' normal (-7)
--- 6387371.845852088
 normal ::
   Applicative f =>
   EllipsoidReaderT f (Double -> Double)
@@ -220,19 +192,6 @@
 wgs84'' r =
   (_Unwrapped # r) wgs84
 
--- |
---
--- >>> ECEF (XY (-5019624) 2618621) (-2927516) ^. runIso (wgs84' earthGeo)
--- LLH {ll = LL {_lat = -0.4799654447089294, _lon = 2.66075442877903}, _height = 100.20987554546446}
---
--- >>> ECEF (XY 9919623 (-3116612)) (-2396517) ^. runIso (wgs84' earthGeo)
--- LLH {ll = LL {_lat = -0.22740831363634992, _lon = -0.30442061911398305}, _height = 4293252.6636643605}
---
--- >>> LLH (LL 0.48 2.661) 100 ^. from (runIso (wgs84' earthGeo))
--- ECEF {_xy = XY {_x = -5020176.908575072, _y = 2617341.3240995244}, _z = 2927710.5079646683}
---
--- >>> LLH (LL (-0.22741) (-0.30442)) 4293252.66 ^. from (runIso (wgs84' earthGeo))
--- ECEF {_xy = XY {_x = 9919621.069754401, _y = -3116604.645933256}, _z = -2396534.4668575544}
 earthGeo ::
   Applicative f =>
   EllipsoidReaderT f (ReifiedIso' ECEF LLH)
diff --git a/src/Data/Geodetic/HasDoubles.hs b/src/Data/Geodetic/HasDoubles.hs
--- a/src/Data/Geodetic/HasDoubles.hs
+++ b/src/Data/Geodetic/HasDoubles.hs
@@ -5,9 +5,7 @@
   HasDoubles(..)
 ) where
 
-import Control.Category(id)
-import Control.Lens(Traversal')
-import Prelude(Double)
+import Papa
 
 class HasDoubles a where
   doubles ::
diff --git a/src/Data/Geodetic/LL.hs b/src/Data/Geodetic/LL.hs
--- a/src/Data/Geodetic/LL.hs
+++ b/src/Data/Geodetic/LL.hs
@@ -8,16 +8,8 @@
 , (<◦>)
 ) where
 
-import Control.Applicative(Applicative((<*>)))
-import Control.Lens(makeClassy, Iso', iso, (^.))
-import Data.Eq(Eq)
-import Data.Functor((<$>))
 import Data.Geodetic.HasDoubles(HasDoubles(doubles))
-import Data.Ord(Ord)
-import Prelude(Fractional((/)), Show, Double, pi, Num((*)))
-
--- $setup
--- >>> import Control.Lens
+import Papa
 
 data LL =
   LL {
@@ -36,13 +28,6 @@
       f a <*>
       f o
 
--- |
---
--- >>> ((27.34, 152.15) ^. degrees)
--- LL {_lat = 0.47717301749524965, _lon = 2.6555184569093724}
---
--- >>> (degrees # LL 0.47717 2.65552)
--- (27.33982711025749,152.15008841258037)
 degrees ::
   Iso'
     (Double, Double)
@@ -54,13 +39,6 @@
     (\(LL t n) -> let r a = a / pi * 180
                   in  (r t, r n))
 
--- |
---
--- >>> 27.34 <◦> 152.15
--- LL {_lat = 0.47717301749524965, _lon = 2.6555184569093724}
---
--- >>> 61.94 <◦> (-152.15)
--- LL {_lat = 1.0810569386852877, _lon = -2.6555184569093724}
 (<◦>) ::
   Double
   -> Double
diff --git a/src/Data/Geodetic/LLH.hs b/src/Data/Geodetic/LLH.hs
--- a/src/Data/Geodetic/LLH.hs
+++ b/src/Data/Geodetic/LLH.hs
@@ -6,14 +6,9 @@
 , HasLLH(..)
 ) where
 
-import Control.Applicative(Applicative((<*>)))
-import Control.Lens(makeClassy, lens)
-import Data.Eq(Eq)
-import Data.Functor((<$>))
 import Data.Geodetic.HasDoubles(HasDoubles(doubles))
-import Data.Geodetic.LL
-import Data.Ord(Ord)
-import Prelude(Show, Double)
+import Data.Geodetic.LL(HasLL(lL), LL)
+import Papa
 
 data LLH =
   LLH {
diff --git a/src/Data/Geodetic/Sphere.hs b/src/Data/Geodetic/Sphere.hs
--- a/src/Data/Geodetic/Sphere.hs
+++ b/src/Data/Geodetic/Sphere.hs
@@ -10,15 +10,8 @@
 , ellipsoidSphere
 ) where
 
-import Control.Lens(makeWrapped, Prism', prism')
-import Data.Eq(Eq((==)))
-import Data.Maybe(Maybe(Just, Nothing))
-import Data.Ord(Ord)
 import Data.Geodetic.Ellipsoid(Ellipsoid(Ellipsoid))
-import Prelude(Double, Show)
-
--- $setup
--- >>> import Control.Lens
+import Papa
 
 newtype Sphere =
   Sphere Double
@@ -26,25 +19,11 @@
 
 makeWrapped ''Sphere
 
--- |
---
--- >>> earthMean
--- Sphere 6367450.0
 earthMean ::
   Sphere
 earthMean =
   Sphere 6367450
 
--- |
---
--- >>> ellipsoidSphere # Sphere 77
--- Ellipsoid {_semiMajor = 77.0, _flattening = 1.0}
---
--- >>> Ellipsoid 77 1 ^? ellipsoidSphere
--- Just (Sphere 77.0)
---
--- >>> Ellipsoid 77 2 ^? ellipsoidSphere
--- Nothing
 ellipsoidSphere ::
   Prism'
     Ellipsoid
diff --git a/src/Data/Geodetic/XY.hs b/src/Data/Geodetic/XY.hs
--- a/src/Data/Geodetic/XY.hs
+++ b/src/Data/Geodetic/XY.hs
@@ -6,13 +6,8 @@
 , HasXY(..)
 ) where
 
-import Control.Applicative(Applicative((<*>)))
-import Control.Lens(makeClassy)
-import Data.Eq(Eq)
-import Data.Functor((<$>))
 import Data.Geodetic.HasDoubles(HasDoubles(doubles))
-import Data.Ord(Ord)
-import Prelude(Show, Double)
+import Papa
 
 data XY =
   XY {
diff --git a/test/doctests.hs b/test/doctests.hs
deleted file mode 100644
--- a/test/doctests.hs
+++ /dev/null
@@ -1,32 +0,0 @@
-module Main where
-
-import Build_doctests (deps)
-import Control.Applicative
-import Control.Monad
-import Data.List
-import System.Directory
-import System.FilePath
-import Test.DocTest
-
-main ::
-  IO ()
-main =
-  getSources >>= \sources -> doctest $
-      "-isrc"
-    : "-idist/build/autogen"
-    : "-optP-include"
-    : "-optPdist/build/autogen/cabal_macros.h"
-    : "-hide-all-packages"
-    : map ("-package="++) deps ++ sources
-
-getSources :: IO [FilePath]
-getSources = filter (isSuffixOf ".hs") <$> go "src"
-  where
-    go dir = do
-      (dirs, files) <- getFilesAndDirectories dir
-      (files ++) . concat <$> mapM go dirs
-
-getFilesAndDirectories :: FilePath -> IO ([FilePath], [FilePath])
-getFilesAndDirectories dir = do
-  c <- map (dir </>) . filter (`notElem` ["..", "."]) <$> getDirectoryContents dir
-  (,) <$> filterM doesDirectoryExist c <*> filterM doesFileExist c
diff --git a/test/hunit_tests.hs b/test/hunit_tests.hs
new file mode 100644
--- /dev/null
+++ b/test/hunit_tests.hs
@@ -0,0 +1,51 @@
+module Main (main) where
+
+import Test.HUnit (Assertion, Test (TestCase, TestList), (@?=), runTestTT, failures, errors)
+
+import Prelude
+import Control.Lens ((^.), (^?), (#), ReifiedIso(runIso), from)
+import Control.Monad (when)
+import System.Exit (exitFailure)
+
+import Data.Geodetic.ECEF
+import Data.Geodetic.Ellipsoid
+import Data.Geodetic.EllipsoidReaderT
+import Data.Geodetic.LL
+import Data.Geodetic.LLH
+import Data.Geodetic.Sphere
+import Data.Geodetic.XY
+
+(@??=) :: Show a => a -> a -> Assertion
+a @??= b = show a @?= show b
+infix 1 @??=
+
+assertions :: [Assertion]
+assertions =
+  [ wgs84' eccentricitySquared @??= 6.6943799901413165e-3
+  , wgs84' eccentricitySquared' @??= 6.694455244784511e-3
+  , wgs84' normal 7 @??= 6387371.845852088
+  , wgs84' normal 71 @??= 6397535.266650572
+  , wgs84' normal 711 @??= 6393308.675975408
+  , wgs84' normal (-7) @??= 6387371.845852088
+  , ECEF (XY (-5019624) 2618621) (-2927516) ^. runIso (wgs84' earthGeo) @?= LLH {ll = LL {_lat = -0.4799654447089294, _lon = 2.66075442877903}, _height = 100.20987554546446}
+  , ECEF (XY 9919623 (-3116612)) (-2396517) ^. runIso (wgs84' earthGeo) @?= LLH {ll = LL {_lat = -0.22740831363634992, _lon = -0.30442061911398305}, _height = 4293252.6636643605}
+  , LLH (LL 0.48 2.661) 100 ^. from (runIso (wgs84' earthGeo)) @?= ECEF {_xy = XY {_x = -5020176.908575072, _y = 2617341.3240995244}, _z = 2927710.5079646683}
+  , LLH (LL (-0.22741) (-0.30442)) 4293252.66 ^. from (runIso (wgs84' earthGeo)) @?= ECEF {_xy = XY {_x = 9919621.069754401, _y = -3116604.645933256}, _z = -2396534.4668575544}
+  , ((27.34, 152.15) ^. degrees) @?= LL {_lat = 0.47717301749524965, _lon = 2.6555184569093724}
+  , (degrees # LL 0.47717 2.65552) @?= (27.33982711025749,152.15008841258037)
+  , 27.34 <◦> 152.15 @?= LL {_lat = 0.47717301749524965, _lon = 2.6555184569093724}
+  , 61.94 <◦> (-152.15) @?= LL {_lat = 1.0810569386852877, _lon = -2.6555184569093724}
+  , earthMean @?= Sphere 6367450.0
+  , ellipsoidSphere # Sphere 77 @?= Ellipsoid {_semiMajor = 77.0, _flattening = 1.0}
+  , Ellipsoid 77 1 ^? ellipsoidSphere @?= Just (Sphere 77.0)
+  , Ellipsoid 77 2 ^? ellipsoidSphere @?= Nothing
+  ]
+
+tests :: Test
+tests =
+  TestList $ fmap TestCase assertions
+
+main :: IO ()
+main = do
+  c <- runTestTT tests
+  when (errors c > 0 || failures c > 0) exitFailure
