diff --git a/LICENCE b/LICENCE
new file mode 100644
--- /dev/null
+++ b/LICENCE
@@ -0,0 +1,27 @@
+Copyright 2013-2014 Tony Morris
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name of the author nor the names of his contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
diff --git a/changelog b/changelog
new file mode 100644
--- /dev/null
+++ b/changelog
@@ -0,0 +1,10 @@
+0.0.11
+
+* Use Optic to overload lenses, prisms and isos.
+
+* Remove use of radians (for now).
+
+0.0.10
+
+This change log started.
+
diff --git a/coordinate.cabal b/coordinate.cabal
--- a/coordinate.cabal
+++ b/coordinate.cabal
@@ -1,7 +1,7 @@
 name:               coordinate
-version:            0.0.10
+version:            0.0.11
 license:            BSD3
-license-file:       etc/LICENCE
+license-file:       LICENCE
 author:             Tony Morris <ʇǝu˙sıɹɹoɯʇ@ןןǝʞsɐɥ>
 maintainer:         Tony Morris
 copyright:          Copyright (C) 2013-2014 Tony Morris
@@ -12,6 +12,7 @@
 bug-reports:        https://github.com/tonymorris/coordinate/issues
 cabal-version:      >= 1.10
 build-type:         Custom
+extra-source-files: changelog
 
 source-repository   head
   type:             git
diff --git a/etc/LICENCE b/etc/LICENCE
deleted file mode 100644
--- a/etc/LICENCE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright 2013-2014 Tony Morris
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-3. Neither the name of the author nor the names of his contributors
-   may be used to endorse or promote products derived from this software
-   without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
diff --git a/src/Data/Geo/Coordinate/Coordinate.hs b/src/Data/Geo/Coordinate/Coordinate.hs
--- a/src/Data/Geo/Coordinate/Coordinate.hs
+++ b/src/Data/Geo/Coordinate/Coordinate.hs
@@ -1,35 +1,31 @@
 {-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
 
 module Data.Geo.Coordinate.Coordinate(
   Coordinate
+, AsCoordinate(..)
 , (.#.)
 , (<°>)
-, (<㎭>)
-, fracCoordinate
-, radianCoordinate
-, HasCoordinate(..)
-, coordinateLatLon
-, coordinateLonLat
-, coordinateDMSLatLon
-, coordinateLatDMSLon
-, coordinateDMSLatDMSLon
 ) where
 
+import Control.Applicative(Applicative)
 import Control.Category(Category(id, (.)))
-import Control.Lens(Iso', Lens', Prism', iso, lens, prism', mapping, swapped, withIso, (^?), (#))
+import Control.Lens(Choice, swapped, Profunctor, Optic', (^.), iso, lens, prism', swapped, (^?), (#))
 import Control.Monad(Monad(return))
 import Data.Eq(Eq)
-import Data.Geo.Coordinate.Latitude(HasLatitude(latitude), Latitude, dmsLatitude, radianLatitude, fracLatitude)
-import Data.Geo.Coordinate.Longitude(HasLongitude(longitude), Longitude, dmsLongitude, radianLongitude, fracLongitude)
-import Data.Geo.Coordinate.DegreesLatitude(HasDegreesLatitude(degreesLatitude), DegreesLatitude)
-import Data.Geo.Coordinate.DegreesLongitude(HasDegreesLongitude(degreesLongitude), DegreesLongitude)
+import Data.Geo.Coordinate.Latitude(AsLatitude(_Latitude), Latitude)
+import Data.Geo.Coordinate.Longitude(AsLongitude(_Longitude), Longitude)
+import Data.Geo.Coordinate.DegreesLatitude(AsDegreesLatitude(_DegreesLatitude), DegreesLatitude)
+import Data.Geo.Coordinate.DegreesLongitude(AsDegreesLongitude(_DegreesLongitude), DegreesLongitude)
 import Data.Geo.Coordinate.Minutes(Minutes)
 import Data.Geo.Coordinate.Seconds(Seconds)
 import Data.Maybe(Maybe)
 import Data.Ord(Ord)
 import Data.Tuple(curry, uncurry)
-import Prelude(Show, Double)
+import Prelude(Double, Functor, Show, Double)
 
 data Coordinate =
   Coordinate
@@ -52,96 +48,109 @@
   -> Double
   -> Maybe Coordinate
 (<°>) =
-  curry (^? fracCoordinate)
+  curry (^? _Coordinate)
 
--- | Build a coordinate from a radian latitude and fractional longitude. Fails
--- if either are out of range.
-(<㎭>) ::
-  Double
-  -> Double
-  -> Maybe Coordinate
-(<㎭>) =
-  curry (^? radianCoordinate)
- 
-coordinatePrism ::
-  Prism' Double Latitude
-  -> Prism' Double Longitude
-  -> Prism' (Double, Double) Coordinate
-coordinatePrism f g =
-  prism'
-    (\x -> let (b, d) = coordinateLatLon # x
-           in (f # b, g # d))
-    (\(lat, lon) ->
-      do lat' <- lat ^? f
-         lon' <- lon ^? g
-         return (Coordinate lat' lon'))
+class AsCoordinate p f s where
+  _Coordinate ::
+    Optic' p f s Coordinate
 
--- | A prism on the pair (below) to a coordinate:
--- 
--- * a fractional latitude to a double between -90 and 90 exclusive.
---
--- * a fractional longitude to a double between -180 and 180 exclusive.
-fracCoordinate ::
-  Prism' (Double, Double) Coordinate
-fracCoordinate =
-  coordinatePrism fracLatitude fracLongitude
+instance AsCoordinate p f Coordinate where
+  _Coordinate =
+    id
 
--- | A prism on the pair (below) to a coordinate:
--- 
--- * a radian latitude to a double between -π/2 and π/2 exclusive.
---
--- * a radian longitude to a double between -π and π exclusive.
-radianCoordinate ::
-  Prism' (Double, Double) Coordinate
-radianCoordinate =
-  coordinatePrism radianLatitude radianLongitude
-  
-coordinateLatLon ::
-  Iso' (Latitude, Longitude) Coordinate
-coordinateLatLon =
-  iso (uncurry Coordinate) (\(Coordinate lat lon) -> (lat, lon))
+instance (Profunctor p, Functor f) => AsCoordinate p f (Latitude, Longitude) where
+  _Coordinate =
+    iso (uncurry Coordinate) (\(Coordinate lat lon) -> (lat, lon))
 
-coordinateLonLat ::
-  Iso' (Longitude, Latitude) Coordinate
-coordinateLonLat =
-  swapped . coordinateLatLon
+instance (Profunctor p, Functor f) => AsCoordinate p f (Longitude, Latitude) where
+  _Coordinate =
+    swapped . _Coordinate
 
-coordinateDMSLatLon ::
-  Iso' ((DegreesLatitude, Minutes, Seconds), Longitude) Coordinate
-coordinateDMSLatLon =
-  swapped . mapping dmsLatitude . coordinateLonLat
+instance (Profunctor p, Functor f) => AsCoordinate p f ((DegreesLatitude, Minutes, Seconds), Longitude) where
+  _Coordinate =
+    iso
+      (\(lat, lon) -> Coordinate (lat ^. _Latitude) lon)
+      (\(Coordinate lat lon) -> (_Latitude # lat, lon))
 
-coordinateLatDMSLon ::
-  Iso' (Latitude, (DegreesLongitude, Minutes, Seconds)) Coordinate
-coordinateLatDMSLon =
-  mapping dmsLongitude . coordinateLatLon
+instance (Profunctor p, Functor f) => AsCoordinate p f (Longitude, (DegreesLatitude, Minutes, Seconds)) where
+  _Coordinate =
+    swapped . _Coordinate
 
-coordinateDMSLatDMSLon ::
-  Iso' ((DegreesLatitude, Minutes, Seconds), (DegreesLongitude, Minutes, Seconds)) Coordinate
-coordinateDMSLatDMSLon =
-  iso (\((td, tm, ts), (nd, nm, ns)) -> Coordinate (withIso dmsLatitude (\k _ -> k (td, tm, ts))) (withIso dmsLongitude (\k _ -> k (nd, nm, ns))))
-      (\(Coordinate lat lon) -> (withIso dmsLatitude (\_ k -> k lat), withIso dmsLongitude (\_ k -> k lon)))
+instance (Profunctor p, Functor f) => AsCoordinate p f (Latitude, (DegreesLongitude, Minutes, Seconds)) where
+  _Coordinate =
+    iso
+      (\(lat, lon) -> Coordinate lat (lon ^. _Longitude))
+      (\(Coordinate lat lon) -> (lat, _Longitude # lon))
 
-class HasCoordinate t where
-  coordinate ::
-    Lens' t Coordinate
+instance (Profunctor p, Functor f) => AsCoordinate p f ((DegreesLongitude, Minutes, Seconds), Latitude) where
+  _Coordinate =
+    swapped . _Coordinate
 
-instance HasCoordinate Coordinate where
-  coordinate =
-    id
+instance (Profunctor p, Functor f) => AsCoordinate p f ((DegreesLatitude, Minutes, Seconds), (DegreesLongitude, Minutes, Seconds)) where
+  _Coordinate =
+    iso
+      (\(lat, lon) -> Coordinate (lat ^. _Latitude) (lon ^. _Longitude))
+      (\(Coordinate lat lon) -> (_Latitude # lat, _Longitude # lon))
 
-instance HasLatitude Coordinate where
-  latitude =
-    lens (\(Coordinate lat _) -> lat) (\(Coordinate _ lon) lat -> Coordinate lat lon)
+instance (Profunctor p, Functor f) => AsCoordinate p f ((DegreesLongitude, Minutes, Seconds), (DegreesLatitude, Minutes, Seconds)) where
+  _Coordinate =
+    swapped . _Coordinate
 
-instance HasLongitude Coordinate where
-  longitude =
-    lens (\(Coordinate _ lon) -> lon) (\(Coordinate lat _) lon -> Coordinate lat lon)
+instance (Choice p, Applicative f) => AsCoordinate p f (Double, Double) where
+  _Coordinate =
+    prism'
+      (\(Coordinate lat lon) -> (_Latitude # lat, _Longitude # lon))
+      (\(lat, lon) ->
+        do lat' <- lat ^? _Latitude
+           lon' <- lon ^? _Longitude
+           return (Coordinate lat' lon'))
 
-instance HasDegreesLatitude Coordinate where
-  degreesLatitude =
-    latitude . degreesLatitude
+instance (Choice p, Applicative f) => AsCoordinate p f (Latitude, Double) where
+  _Coordinate =
+    prism'
+      (\(Coordinate lat lon) -> (lat, _Longitude # lon))
+      (\(lat, lon) ->
+        do lon' <- lon ^? _Longitude
+           return (Coordinate lat lon'))
 
-instance HasDegreesLongitude Coordinate where
-  degreesLongitude =
-    longitude . degreesLongitude
+instance (Choice p, Applicative f) => AsCoordinate p f (Double, Longitude) where
+  _Coordinate =
+    prism'
+      (\(Coordinate lat lon) -> (_Latitude # lat, lon))
+      (\(lat, lon) ->
+        do lat' <- lat ^? _Latitude
+           return (Coordinate lat' lon))
+
+instance (Choice p, Applicative f) => AsCoordinate p f ((DegreesLatitude, Minutes, Seconds), Double) where
+  _Coordinate =
+    prism'
+      (\(Coordinate lat lon) -> (_Latitude # lat, _Longitude # lon))
+      (\(lat, lon) ->
+        do lat' <- lat ^? _Latitude
+           lon' <- lon ^? _Longitude
+           return (Coordinate lat' lon'))
+
+instance (Choice p, Applicative f) => AsCoordinate p f (Double, (DegreesLongitude, Minutes, Seconds)) where
+  _Coordinate =
+    prism'
+      (\(Coordinate lat lon) -> (_Latitude # lat, _Longitude # lon))
+      (\(lat, lon) ->
+        do lat' <- lat ^? _Latitude
+           lon' <- lon ^? _Longitude
+           return (Coordinate lat' lon'))
+
+instance (p ~ (->), Functor f) => AsLatitude p f Coordinate where
+  _Latitude =
+    lens (\(Coordinate lat _) -> lat) (\(Coordinate _ lon) lat -> Coordinate lat lon)
+    
+instance (p ~ (->), Functor f) => AsDegreesLatitude p f Coordinate where
+  _DegreesLatitude =
+    _Latitude . _DegreesLatitude
+
+instance (p ~ (->), Functor f) => AsLongitude p f Coordinate where
+  _Longitude =
+    lens (\(Coordinate _ lon) -> lon) (\(Coordinate lat _) lon -> Coordinate lat lon)
+    
+instance (p ~ (->), Functor f) => AsDegreesLongitude p f Coordinate where
+  _DegreesLongitude =
+    _Longitude . _DegreesLongitude
diff --git a/src/Data/Geo/Coordinate/DegreesLatitude.hs b/src/Data/Geo/Coordinate/DegreesLatitude.hs
--- a/src/Data/Geo/Coordinate/DegreesLatitude.hs
+++ b/src/Data/Geo/Coordinate/DegreesLatitude.hs
@@ -1,13 +1,15 @@
 {-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FlexibleInstances #-}
 
 module Data.Geo.Coordinate.DegreesLatitude(
   DegreesLatitude
-, HasDegreesLatitude(..)
-, nDegreesLatitude
+, AsDegreesLatitude(..)
 ) where
 
+import Control.Applicative(Applicative)
 import Control.Category(Category(id))
-import Control.Lens(Prism', Lens', prism')
+import Control.Lens(Optic', Choice, prism')
 import Data.Bool((&&))
 import Data.Eq(Eq)
 import Data.Int(Int)
@@ -24,41 +26,39 @@
   DegreesLatitude Int
   deriving (Eq, Ord, Show)
 
+class AsDegreesLatitude p f s where
+  _DegreesLatitude ::
+    Optic' p f s DegreesLatitude
+
+instance AsDegreesLatitude p f DegreesLatitude where
+  _DegreesLatitude =
+    id
+
 -- | A prism on degrees latitude to an integer between -90 and 90 exclusive.
 --
--- >>> 7 ^? nDegreesLatitude
+-- >>> (7 :: Int) ^? _DegreesLatitude
 -- Just (DegreesLatitude 7)
 --
--- >>> 0 ^? nDegreesLatitude
+-- >>> (0 :: Int) ^? _DegreesLatitude
 -- Just (DegreesLatitude 0)
 --
--- >>> 89 ^? nDegreesLatitude
+-- >>> (89 :: Int) ^? _DegreesLatitude
 -- Just (DegreesLatitude 89)
 --
--- >>> 90 ^? nDegreesLatitude
+-- >>> (90 :: Int) ^? _DegreesLatitude
 -- Nothing
 --
--- >>> (-89) ^? nDegreesLatitude
+-- >>> (-89 :: Int) ^? _DegreesLatitude
 -- Just (DegreesLatitude (-89))
 --
--- >>> (-90) ^? nDegreesLatitude
+-- >>> (-90 :: Int) ^? _DegreesLatitude
 -- Nothing
 --
--- prop> all (\m -> nDegreesLatitude # m == n) (n ^? nDegreesLatitude)
-nDegreesLatitude ::
-  Prism' Int DegreesLatitude
-nDegreesLatitude =
-  prism'
-    (\(DegreesLatitude i) -> i)
-    (\i -> if i > -90 && i < 90
-             then Just (DegreesLatitude i)
-             else Nothing)
-
-class HasDegreesLatitude t where
-  degreesLatitude ::
-    Lens' t DegreesLatitude
-
-instance HasDegreesLatitude DegreesLatitude where
-  degreesLatitude =
-    id
-
+-- prop> all (\m -> _DegreesLatitude # m == (n :: Int)) (n ^? _DegreesLatitude)
+instance (Choice p, Applicative f) => AsDegreesLatitude p f Int where
+  _DegreesLatitude =
+    prism'
+      (\(DegreesLatitude i) -> i)
+      (\i -> if i > -90 && i < 90
+               then Just (DegreesLatitude i)
+               else Nothing)
diff --git a/src/Data/Geo/Coordinate/DegreesLongitude.hs b/src/Data/Geo/Coordinate/DegreesLongitude.hs
--- a/src/Data/Geo/Coordinate/DegreesLongitude.hs
+++ b/src/Data/Geo/Coordinate/DegreesLongitude.hs
@@ -1,13 +1,15 @@
 {-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FlexibleInstances #-}
 
 module Data.Geo.Coordinate.DegreesLongitude(
   DegreesLongitude
-, HasDegreesLongitude(..)
-, nDegreesLongitude
+, AsDegreesLongitude(..)
 ) where
 
+import Control.Applicative(Applicative)
 import Control.Category(Category(id))
-import Control.Lens(Prism', Lens', prism')
+import Control.Lens(Optic', Choice, prism')
 import Data.Bool((&&))
 import Data.Eq(Eq)
 import Data.Int(Int)
@@ -24,40 +26,39 @@
   DegreesLongitude Int
   deriving (Eq, Ord, Show)
 
+class AsDegreesLongitude p f s where
+  _DegreesLongitude ::
+    Optic' p f s DegreesLongitude
+
+instance AsDegreesLongitude p f DegreesLongitude where
+  _DegreesLongitude =
+    id
+
 -- | A prism on degrees longitude to an integer between -180 and 180 exclusive.
 --
--- >>> 7 ^? nDegreesLongitude
+-- >>> (7 :: Int) ^? _DegreesLongitude
 -- Just (DegreesLongitude 7)
 --
--- >>> 0 ^? nDegreesLongitude
+-- >>> (0 :: Int) ^? _DegreesLongitude
 -- Just (DegreesLongitude 0)
 --
--- >>> 179 ^? nDegreesLongitude
+-- >>> (179 :: Int) ^? _DegreesLongitude
 -- Just (DegreesLongitude 179)
 --
--- >>> 180 ^? nDegreesLongitude
+-- >>> (180 :: Int) ^? _DegreesLongitude
 -- Nothing
 --
--- >>> (-179) ^? nDegreesLongitude
+-- >>> (-179 :: Int) ^? _DegreesLongitude
 -- Just (DegreesLongitude (-179))
 --
--- >>> (-180) ^? nDegreesLongitude
+-- >>> (-180 :: Int) ^? _DegreesLongitude
 -- Nothing
 --
--- prop> all (\m -> nDegreesLongitude # m == n) (n ^? nDegreesLongitude)
-nDegreesLongitude ::
-  Prism' Int DegreesLongitude
-nDegreesLongitude  =
-  prism'
-    (\(DegreesLongitude i) -> i)
-    (\i -> if i > -180 && i < 180
-             then Just (DegreesLongitude i)
-             else Nothing)
-
-class HasDegreesLongitude t where
-  degreesLongitude ::
-    Lens' t DegreesLongitude
-
-instance HasDegreesLongitude DegreesLongitude where
-  degreesLongitude =
-    id
+-- prop> all (\m -> _DegreesLongitude # m == (n :: Int)) (n ^? _DegreesLongitude)
+instance (Choice p, Applicative f) => AsDegreesLongitude p f Int where
+  _DegreesLongitude =
+    prism'
+      (\(DegreesLongitude i) -> i)
+      (\i -> if i > -180 && i < 180
+               then Just (DegreesLongitude i)
+               else Nothing)
diff --git a/src/Data/Geo/Coordinate/Latitude.hs b/src/Data/Geo/Coordinate/Latitude.hs
--- a/src/Data/Geo/Coordinate/Latitude.hs
+++ b/src/Data/Geo/Coordinate/Latitude.hs
@@ -1,25 +1,27 @@
 {-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
 
 module Data.Geo.Coordinate.Latitude(
   Latitude
-, HasLatitude(..)
-, dmsLatitude
-, fracLatitude
-, radianLatitude
+, AsLatitude(..)
 ) where
 
-import Control.Category(Category(id, (.)))
-import Control.Lens(Iso', Prism', Lens', iso, prism', lens, (#), (^?))
+import Control.Applicative(Applicative)
+import Control.Category(Category(id))
+import Control.Lens(Choice, Profunctor, Optic', iso, prism', lens, (#), (^?))
 import Control.Monad(Monad(return))
 import Data.Eq(Eq)
-import Data.Geo.Coordinate.DegreesLatitude(HasDegreesLatitude(degreesLatitude), DegreesLatitude, nDegreesLatitude)
-import Data.Geo.Coordinate.Minutes(HasMinutes(minutes), Minutes, nMinutes)
-import Data.Geo.Coordinate.Seconds(HasSeconds(seconds), Seconds, nSeconds)
+import Data.Geo.Coordinate.DegreesLatitude(DegreesLatitude, AsDegreesLatitude(_DegreesLatitude))
+import Data.Geo.Coordinate.Minutes(AsMinutes(_Minutes), Minutes)
+import Data.Geo.Coordinate.Seconds(AsSeconds(_Seconds), Seconds)
 import Data.Ord(Ord((<)))
-import Prelude(Double, Show, Num((+), (*), (-), abs), Floating(pi), Fractional((/)), properFraction, fromIntegral)
+import Prelude(Functor, Double, Show, Int, Num((+), (*), (-), abs), Fractional((/)), properFraction, fromIntegral)
 
 -- $setup
 -- >>> import Prelude(Functor(..))
+-- >>> import Data.Maybe
 
 data Latitude =
   Latitude
@@ -28,139 +30,107 @@
     Seconds
   deriving (Eq, Ord, Show)
 
+class AsLatitude p f s where
+  _Latitude ::
+    Optic' p f s Latitude
+
+instance AsLatitude p f Latitude where
+  _Latitude =
+    id
+
 -- | An isomorphism on the triple of degrees latitude, minutes, seconds to a latitude.
 --
--- >>> do deg <- 7 ^? nDegreesLatitude; min <- 7 ^? nMinutes; sec <- 7 ^? nSeconds; (deg, min, sec) ^? dmsLatitude
+-- >>> do deg <- (7 :: Int) ^? _DegreesLatitude; min <- (7 :: Int) ^? _Minutes; sec <- (7 :: Double) ^? _Seconds; (deg, min, sec) ^? _Latitude :: Maybe Latitude
 -- Just (Latitude (DegreesLatitude 7) (Minutes 7) (Seconds 7.0000))
 --
--- >>> do deg <- 89 ^? nDegreesLatitude; min <- 59 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLatitude
+-- >>> do deg <- (89 :: Int) ^? _DegreesLatitude; min <- (59 :: Int) ^? _Minutes; sec <- (59 :: Double) ^? _Seconds; (deg, min, sec) ^? _Latitude :: Maybe Latitude
 -- Just (Latitude (DegreesLatitude 89) (Minutes 59) (Seconds 59.0000))
 --
--- >>> do deg <- (-7) ^? nDegreesLatitude; min <- 7 ^? nMinutes; sec <- 7 ^? nSeconds; (deg, min, sec) ^? dmsLatitude
+-- >>> do deg <- (-7 :: Int) ^? _DegreesLatitude; min <- (7 :: Int) ^? _Minutes; sec <- (7 :: Double) ^? _Seconds; (deg, min, sec) ^? _Latitude :: Maybe Latitude
 -- Just (Latitude (DegreesLatitude (-7)) (Minutes 7) (Seconds 7.0000))
 --
--- >>> do deg <- (-89) ^? nDegreesLatitude; min <- 59 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLatitude
+-- >>> do deg <- (-89 :: Int) ^? _DegreesLatitude; min <- (59 :: Int) ^? _Minutes; sec <- (59 :: Double) ^? _Seconds; (deg, min, sec) ^? _Latitude :: Maybe Latitude
 -- Just (Latitude (DegreesLatitude (-89)) (Minutes 59) (Seconds 59.0000))
 --
--- >>> do deg <- 90 ^? nDegreesLatitude; min <- 59 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLatitude
+-- >>> do deg <- (90 :: Int) ^? _DegreesLatitude; min <- (59 :: Int) ^? _Minutes; sec <- (59 :: Double) ^? _Seconds; (deg, min, sec) ^? _Latitude :: Maybe Latitude
 -- Nothing
 --
--- >>> do deg <- 89 ^? nDegreesLatitude; min <- 60 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLatitude
+-- >>> do deg <- (89 :: Int) ^? _DegreesLatitude; min <- (60 :: Int) ^? _Minutes; sec <- (59 :: Double) ^? _Seconds; (deg, min, sec) ^? _Latitude :: Maybe Latitude
 -- Nothing
 --
--- >>> do deg <- 89 ^? nDegreesLatitude; min <- 59 ^? nMinutes; sec <- 60 ^? nSeconds; (deg, min, sec) ^? dmsLatitude
+-- >>> do deg <- (89 :: Int) ^? _DegreesLatitude; min <- (59 :: Int) ^? _Minutes; sec <- (60 :: Double) ^? _Seconds; (deg, min, sec) ^? _Latitude :: Maybe Latitude
 -- Nothing
 --
--- >>> fmap (dmsLatitude #)  (7 ^? fracLatitude)
+-- >>> fmap (\x -> _Latitude # x :: (DegreesLatitude, Minutes, Seconds))  ((7 :: Double) ^? _Latitude :: Maybe Latitude)
 -- Just (DegreesLatitude 7,Minutes 0,Seconds 0.0000)
 --
--- >>> fmap (dmsLatitude #)  (7.12 ^? fracLatitude)
+-- >>> fmap (\x -> _Latitude # x :: (DegreesLatitude, Minutes, Seconds))  ((7.12 :: Double) ^? _Latitude :: Maybe Latitude)
 -- Just (DegreesLatitude 7,Minutes 7,Seconds 12.0000)
-dmsLatitude ::
-  Iso' (DegreesLatitude, Minutes, Seconds) Latitude
-dmsLatitude =
-  iso (\(d, m, s) -> Latitude d m s) (\(Latitude d m s) -> (d, m, s))
+instance (Profunctor p, Functor f) => AsLatitude p f (DegreesLatitude, Minutes, Seconds) where
+  _Latitude =
+    iso (\(d, m, s) -> Latitude d m s) (\(Latitude d m s) -> (d, m, s))
 
 -- | A prism on latitude to a double between -90 and 90 exclusive.
 --
--- >>> 7 ^? fracLatitude
+-- >>> (7 :: Double) ^? _Latitude :: Maybe Latitude
 -- Just (Latitude (DegreesLatitude 7) (Minutes 0) (Seconds 0.0000))
 --
--- >>> (-7) ^? fracLatitude
+-- >>> (-7 :: Double) ^? _Latitude :: Maybe Latitude
 -- Just (Latitude (DegreesLatitude (-7)) (Minutes 0) (Seconds 0.0000))
 --
--- >>> 7.12 ^? fracLatitude
+-- >>> (7.12 :: Double) ^? _Latitude :: Maybe Latitude
 -- Just (Latitude (DegreesLatitude 7) (Minutes 7) (Seconds 12.0000))
 --
--- >>> (-7.12) ^? fracLatitude
+-- >>> (-7.12 :: Double) ^? _Latitude :: Maybe Latitude
 -- Just (Latitude (DegreesLatitude (-7)) (Minutes 7) (Seconds 12.0000))
 --
--- >>> fmap (fracLatitude #) (7.12 ^? fracLatitude)
+-- >>> fmap (\x -> _Latitude # x :: Double) ((7.12 :: Double) ^? _Latitude :: Maybe Latitude)
 -- Just 7.12
 --
--- >>> fmap (fracLatitude #) ((-7.12) ^? fracLatitude)
+-- >>> fmap (\x -> _Latitude # x :: Double) ((-7.12 :: Double) ^? _Latitude :: Maybe Latitude)
 -- Just (-7.12)
 --
--- >>> 90 ^? fracLatitude
+-- >>> (90 :: Double) ^? _Latitude :: Maybe Latitude
 -- Nothing
 --
--- >>> (-90) ^? fracLatitude
+-- >>> (-90 :: Double) ^? _Latitude :: Maybe Latitude
 -- Nothing
 --
--- >>> 15.63791 ^? fracLatitude
+-- >>> (15.63791 :: Double) ^? _Latitude :: Maybe Latitude
 -- Just (Latitude (DegreesLatitude 15) (Minutes 38) (Seconds 16.4760))
 --
--- >>> 89.1 ^? fracLatitude
+-- >>> (89.1 :: Double) ^? _Latitude :: Maybe Latitude
 -- Just (Latitude (DegreesLatitude 89) (Minutes 5) (Seconds 60.0000))
 --
--- >>> 89.2 ^? fracLatitude
+-- >>> (89.2 :: Double) ^? _Latitude :: Maybe Latitude
 -- Just (Latitude (DegreesLatitude 89) (Minutes 12) (Seconds 0.0000))
 --
--- >>> fmap (fracLatitude #) (do deg <- 7 ^? nDegreesLatitude; min <- 7 ^? nMinutes; sec <- 7 ^? nSeconds; (deg, min, sec) ^? dmsLatitude)
+-- >>> fmap (\x -> _Latitude # x :: Double) (do deg <- (7 :: Int) ^? _DegreesLatitude; min <- (7 :: Int) ^? _Minutes; sec <- (7 :: Double) ^? _Seconds; (deg, min, sec) ^? _Latitude :: Maybe Latitude)
 -- Just 7.118611111111111
 --
--- >>> fmap (fracLatitude #) (do deg <- 89 ^? nDegreesLatitude; min <- 15 ^? nMinutes; sec <- 6 ^? nSeconds; (deg, min, sec) ^? dmsLatitude)
+-- >>> fmap (\x -> _Latitude # x  :: Double) (do deg <- (89 :: Int) ^? _DegreesLatitude; min <- (15 :: Int) ^? _Minutes; sec <- (6 :: Double) ^? _Seconds; (deg, min, sec) ^? _Latitude :: Maybe Latitude)
 -- Just 89.25166666666667
-fracLatitude ::
-  Prism' Double Latitude
-fracLatitude =
-  prism' (\(Latitude d m s) ->
-    let p = fromIntegral (nDegreesLatitude # d)
-        q = (fromIntegral (nMinutes # m) / 60) + (nSeconds # s) / 3600
+instance (Choice p, Applicative f) => AsLatitude p f Double where
+  _Latitude =
+    prism' (\(Latitude d m s) ->
+    let p = fromIntegral (_DegreesLatitude # d :: Int)
+        q = (fromIntegral (_Minutes # m :: Int) / 60) + (_Seconds # s) / 3600
     in (if p < 0 then (-) else (+)) p q)
     (\x -> let (d, z) = properFraction x
                (m, s) = properFraction ((z :: Double) * 60)
-           in do d' <- d ^? nDegreesLatitude
-                 m' <- abs m ^? nMinutes
-                 s' <- (abs s * 60) ^? nSeconds
+           in do d' <- (d :: Int) ^? _DegreesLatitude
+                 m' <- (abs m :: Int) ^? _Minutes
+                 s' <- (abs s * 60) ^? _Seconds
                  return (Latitude d' m' s'))
 
--- | A prism on latitude to a double between -π/2 and π/2 exclusive.
---
--- >>> 0.2 ^? radianLatitude
--- Just (Latitude (DegreesLatitude 11) (Minutes 27) (Seconds 32.9612))
---
--- >>> 1.3 ^? radianLatitude
--- Just (Latitude (DegreesLatitude 74) (Minutes 29) (Seconds 4.2481))
---
--- >>> (-1.3) ^? radianLatitude
--- Just (Latitude (DegreesLatitude (-74)) (Minutes 29) (Seconds 4.2481))
---
--- >>> 1.5707963 ^? radianLatitude
--- Just (Latitude (DegreesLatitude 89) (Minutes 59) (Seconds 59.9945))
---
--- >>> 1.58 ^? radianLatitude
--- Nothing
---
--- >>> (-1.58) ^? radianLatitude
--- Nothing
---
--- >>> fmap (radianLatitude #) (do deg <- 7 ^? nDegreesLatitude; min <- 7 ^? nMinutes; sec <- 7 ^? nSeconds; (deg, min, sec) ^? dmsLatitude)
--- Just 0.12424320205794079
---
--- >>> fmap (radianLatitude #) (do deg <- 89 ^? nDegreesLatitude; min <- 15 ^? nMinutes; sec <- 6 ^? nSeconds; (deg, min, sec) ^? dmsLatitude)
--- Just 1.5577354462258057
-radianLatitude ::
-  Prism' Double Latitude
-radianLatitude =
-  iso (\n -> n * 180 / pi) (\n -> n * pi / 180) . fracLatitude
-
-class HasLatitude t where
-  latitude ::
-    Lens' t Latitude
-
-instance HasLatitude Latitude where
-  latitude =
-    id
-
-instance HasDegreesLatitude Latitude where
-  degreesLatitude =
+instance (p ~ (->), Functor f) => AsDegreesLatitude p f Latitude where
+  _DegreesLatitude =
     lens (\(Latitude d _ _) -> d) (\(Latitude _ m s) d -> Latitude d m s)
 
-instance HasMinutes Latitude where
-  minutes =
+instance (p ~ (->), Functor f) => AsMinutes p f Latitude where
+  _Minutes =
     lens (\(Latitude _ m _) -> m) (\(Latitude d _ s) m -> Latitude d m s)
 
-instance HasSeconds Latitude where
-  seconds =
+instance (p ~ (->), Functor f) => AsSeconds p f Latitude where
+  _Seconds =
     lens (\(Latitude _ _ s) -> s) (\(Latitude d m _) s -> Latitude d m s)
diff --git a/src/Data/Geo/Coordinate/Longitude.hs b/src/Data/Geo/Coordinate/Longitude.hs
--- a/src/Data/Geo/Coordinate/Longitude.hs
+++ b/src/Data/Geo/Coordinate/Longitude.hs
@@ -1,26 +1,28 @@
 {-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
 
 module Data.Geo.Coordinate.Longitude(
   Longitude
-, HasLongitude(..)
-, dmsLongitude
-, fracLongitude
-, radianLongitude
+, AsLongitude(..)
+, AsFracLongitude(..)
 ) where
 
-
-import Control.Category(Category(id, (.)))
-import Control.Lens(Iso', Prism', Lens', iso, prism', lens, (#), (^?))
+import Control.Applicative(Applicative)
+import Control.Category(Category(id))
+import Control.Lens(Choice, Profunctor, Optic', Prism', iso, prism', lens, (#), (^?))
 import Control.Monad(Monad(return))
 import Data.Eq(Eq)
-import Data.Geo.Coordinate.DegreesLongitude(HasDegreesLongitude(degreesLongitude), DegreesLongitude, nDegreesLongitude)
-import Data.Geo.Coordinate.Minutes(HasMinutes(minutes), Minutes, nMinutes)
-import Data.Geo.Coordinate.Seconds(HasSeconds(seconds), Seconds, nSeconds)
+import Data.Geo.Coordinate.DegreesLongitude(DegreesLongitude, AsDegreesLongitude(_DegreesLongitude))
+import Data.Geo.Coordinate.Minutes(AsMinutes(_Minutes), Minutes)
+import Data.Geo.Coordinate.Seconds(AsSeconds(_Seconds), Seconds)
 import Data.Ord(Ord((<)))
-import Prelude(Double, Show, Num((+), (*), (-), abs), Floating(pi), Fractional((/)), properFraction, fromIntegral)
+import Prelude(Functor, Double, Show, Int, Num((+), (*), (-), abs), Fractional((/)), properFraction, fromIntegral)
 
 -- $setup
 -- >>> import Prelude(Functor(..))
+-- >>> import Data.Maybe
 
 data Longitude =
   Longitude
@@ -29,139 +31,166 @@
     Seconds
   deriving (Eq, Ord, Show)
 
+class AsLongitude p f s where
+  _Longitude ::
+    Optic' p f s Longitude
+
+instance AsLongitude p f Longitude where
+  _Longitude =
+    id
+
 -- | An isomorphism on the triple of degrees longitude, minutes, seconds to a longitude.
 --
--- >>> do deg <- 7 ^? nDegreesLongitude; min <- 7 ^? nMinutes; sec <- 7 ^? nSeconds; (deg, min, sec) ^? dmsLongitude
+-- >>> do deg <- (7 :: Int) ^? _DegreesLongitude; min <- (7 :: Int) ^? _Minutes; sec <- (7 :: Double) ^? _Seconds; (deg, min, sec) ^? _Longitude :: Maybe Longitude
 -- Just (Longitude (DegreesLongitude 7) (Minutes 7) (Seconds 7.0000))
 --
--- >>> do deg <- 179 ^? nDegreesLongitude; min <- 59 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLongitude
+-- >>> do deg <- (179 :: Int) ^? _DegreesLongitude; min <- (59 :: Int) ^? _Minutes; sec <- (59 :: Double) ^? _Seconds; (deg, min, sec) ^? _Longitude :: Maybe Longitude
 -- Just (Longitude (DegreesLongitude 179) (Minutes 59) (Seconds 59.0000))
 --
--- >>> do deg <- (-7) ^? nDegreesLongitude; min <- 7 ^? nMinutes; sec <- 7 ^? nSeconds; (deg, min, sec) ^? dmsLongitude
+-- >>> do deg <- (-7 :: Int) ^? _DegreesLongitude; min <- (7 :: Int) ^? _Minutes; sec <- (7 :: Double) ^? _Seconds; (deg, min, sec) ^? _Longitude :: Maybe Longitude
 -- Just (Longitude (DegreesLongitude (-7)) (Minutes 7) (Seconds 7.0000))
 --
--- >>> do deg <- (-179) ^? nDegreesLongitude; min <- 59 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLongitude
+-- >>> do deg <- (-179 :: Int) ^? _DegreesLongitude; min <- (59 :: Int) ^? _Minutes; sec <- (59 :: Double) ^? _Seconds; (deg, min, sec) ^? _Longitude :: Maybe Longitude
 -- Just (Longitude (DegreesLongitude (-179)) (Minutes 59) (Seconds 59.0000))
 --
--- >>> do deg <- 180 ^? nDegreesLongitude; min <- 59 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLongitude
+-- >>> do deg <- (180 :: Int) ^? _DegreesLongitude; min <- (59 :: Int) ^? _Minutes; sec <- (59 :: Double) ^? _Seconds; (deg, min, sec) ^? _Longitude :: Maybe Longitude
 -- Nothing
 --
--- >>> do deg <- 179 ^? nDegreesLongitude; min <- 60 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLongitude
+-- >>> do deg <- (179 :: Int) ^? _DegreesLongitude; min <- (60 :: Int) ^? _Minutes; sec <- (59 :: Double) ^? _Seconds; (deg, min, sec) ^? _Longitude :: Maybe Longitude
 -- Nothing
 --
--- >>> do deg <- 179 ^? nDegreesLongitude; min <- 59 ^? nMinutes; sec <- 60 ^? nSeconds; (deg, min, sec) ^? dmsLongitude
+-- >>> do deg <- (179 :: Int) ^? _DegreesLongitude; min <- (59 :: Int) ^? _Minutes; sec <- (60 :: Double) ^? _Seconds; (deg, min, sec) ^? _Longitude :: Maybe Longitude
 -- Nothing
 --
--- >>> fmap (dmsLongitude #)  (7 ^? fracLongitude)
+-- >>> fmap (\x -> _Longitude # x :: (DegreesLongitude, Minutes, Seconds))  (7 ^? fracLongitude :: Maybe Longitude)
 -- Just (DegreesLongitude 7,Minutes 0,Seconds 0.0000)
 --
--- >>> fmap (dmsLongitude #)  (7.12 ^? fracLongitude)
+-- >>> fmap (\x -> _Longitude # x :: (DegreesLongitude, Minutes, Seconds))  (7.12 ^? fracLongitude :: Maybe Longitude)
 -- Just (DegreesLongitude 7,Minutes 7,Seconds 12.0000)
-dmsLongitude ::
-  Iso' (DegreesLongitude, Minutes, Seconds) Longitude
-dmsLongitude =
-  iso (\(d, m, s) -> Longitude d m s) (\(Longitude d m s) -> (d, m, s))
+instance (Profunctor p, Functor f) => AsLongitude p f (DegreesLongitude, Minutes, Seconds) where
+  _Longitude =
+    iso (\(d, m, s) -> Longitude d m s) (\(Longitude d m s) -> (d, m, s))
 
 -- | A prism on longitude to a double between -180 and 180 exclusive.
 --
--- >>> 7 ^? fracLongitude
+-- >>> (7 :: Double) ^? _Longitude :: Maybe Longitude
 -- Just (Longitude (DegreesLongitude 7) (Minutes 0) (Seconds 0.0000))
 --
--- >>> (-7) ^? fracLongitude
+-- >>> (-7 :: Double) ^? _Longitude :: Maybe Longitude
 -- Just (Longitude (DegreesLongitude (-7)) (Minutes 0) (Seconds 0.0000))
 --
--- >>> 7.12 ^? fracLongitude
+-- >>> (7.12 :: Double) ^? _Longitude :: Maybe Longitude
 -- Just (Longitude (DegreesLongitude 7) (Minutes 7) (Seconds 12.0000))
 --
--- >>> (-7.12) ^? fracLongitude
+-- >>> (-7.12 :: Double) ^? _Longitude :: Maybe Longitude
 -- Just (Longitude (DegreesLongitude (-7)) (Minutes 7) (Seconds 12.0000))
 --
--- >>> fmap (fracLongitude #) (7.12 ^? fracLongitude)
+-- >>> fmap (\x -> _Longitude # x  :: Double) ((7.12 :: Double) ^? _Longitude :: Maybe Longitude)
 -- Just 7.12
 --
--- >>> fmap (fracLongitude #) ((-7.12) ^? fracLongitude)
+-- >>> fmap (\x -> _Longitude # x :: Double) ((-7.12 :: Double) ^? _Longitude :: Maybe Longitude)
 -- Just (-7.12)
 --
--- >>> 180 ^? fracLongitude
+-- >>> (180 :: Double) ^? _Longitude :: Maybe Longitude
 -- Nothing
 --
--- >>> (-180) ^? fracLongitude
+-- >>> (-180 :: Double) ^? _Longitude :: Maybe Longitude
 -- Nothing
 --
--- >>> 15.63791 ^? fracLongitude
+-- >>> (15.63791 :: Double) ^? _Longitude :: Maybe Longitude
 -- Just (Longitude (DegreesLongitude 15) (Minutes 38) (Seconds 16.4760))
 --
--- >>> 179.1 ^? fracLongitude
+-- >>> (179.1 :: Double) ^? _Longitude :: Maybe Longitude
 -- Just (Longitude (DegreesLongitude 179) (Minutes 5) (Seconds 60.0000))
 --
--- >>> 179.2 ^? fracLongitude
+-- >>> (179.2 :: Double) ^? _Longitude :: Maybe Longitude
 -- Just (Longitude (DegreesLongitude 179) (Minutes 11) (Seconds 60.0000))
 --
--- >>> fmap (fracLongitude #) (do deg <- 7 ^? nDegreesLongitude; min <- 7 ^? nMinutes; sec <- 7 ^? nSeconds; (deg, min, sec) ^? dmsLongitude)
+-- >>> fmap (\x -> _Longitude # x :: Double) (do deg <- (7 :: Int) ^? _DegreesLongitude; min <- (7 :: Int) ^? _Minutes; sec <- (7 :: Double) ^? _Seconds; (deg, min, sec) ^? _Longitude :: Maybe Longitude)
 -- Just 7.118611111111111
 --
--- >>> fmap (fracLongitude #) (do deg <- 179 ^? nDegreesLongitude; min <- 15 ^? nMinutes; sec <- 6 ^? nSeconds; (deg, min, sec) ^? dmsLongitude)
+-- >>> fmap (\x -> _Longitude # x :: Double) (do deg <- (179 :: Int) ^? _DegreesLongitude; min <- (15 :: Int) ^? _Minutes; sec <- (6 :: Double) ^? _Seconds; (deg, min, sec) ^? _Longitude :: Maybe Longitude)
 -- Just 179.25166666666667
-fracLongitude ::
-  Prism' Double Longitude
-fracLongitude =
-  prism' (\(Longitude d m s) ->
-    let p = fromIntegral (nDegreesLongitude # d)
-        q = (fromIntegral (nMinutes # m) / 60) + (nSeconds # s) / 3600
-    in (if p < 0 then (-) else (+)) p q)
-    (\x -> let (d, z) = properFraction x
-               (m, s) = properFraction ((z :: Double) * 60)
-           in do d' <- d ^? nDegreesLongitude
-                 m' <- abs m ^? nMinutes
-                 s' <- (abs s * 60) ^? nSeconds
-                 return (Longitude d' m' s'))
+instance (Choice p, Applicative f) => AsLongitude p f Double where
+  _Longitude =
+    prism' (\(Longitude d m s) ->
+      let p = fromIntegral (_DegreesLongitude # d :: Int)
+          q = (fromIntegral (_Minutes # m :: Int) / 60) + (_Seconds # s) / 3600
+      in (if p < 0 then (-) else (+)) p q)
+      (\x -> let (d, z) = properFraction x
+                 (m, s) = properFraction ((z :: Double) * 60)
+             in do d' <- (d :: Int) ^? _DegreesLongitude
+                   m' <- (abs m :: Int) ^? _Minutes
+                   s' <- (abs s * 60) ^? _Seconds
+                   return (Longitude d' m' s'))
 
--- | A prism on longitude to a double between -π and π exclusive.
+
+-- | A prism on longitude to a double between -180 and 180 exclusive.
+class AsFracLongitude t where
+  fracLongitude ::
+    Prism' Double t
+
+-- | A prism on longitude to a double between -180 and 180 exclusive.
 --
--- >>> 0.2 ^? radianLongitude
--- Just (Longitude (DegreesLongitude 11) (Minutes 27) (Seconds 32.9612))
+-- >>> 7 ^? fracLongitude :: Maybe Longitude
+-- Just (Longitude (DegreesLongitude 7) (Minutes 0) (Seconds 0.0000))
 --
--- >>> 1.3 ^? radianLongitude
--- Just (Longitude (DegreesLongitude 74) (Minutes 29) (Seconds 4.2481))
+-- >>> (-7) ^? fracLongitude :: Maybe Longitude
+-- Just (Longitude (DegreesLongitude (-7)) (Minutes 0) (Seconds 0.0000))
 --
--- >>> (-1.3) ^? radianLongitude
--- Just (Longitude (DegreesLongitude (-74)) (Minutes 29) (Seconds 4.2481))
+-- >>> 7.12 ^? fracLongitude :: Maybe Longitude
+-- Just (Longitude (DegreesLongitude 7) (Minutes 7) (Seconds 12.0000))
 --
--- >>> 3.14159 ^? radianLongitude
--- Just (Longitude (DegreesLongitude 179) (Minutes 59) (Seconds 59.4527))
+-- >>> (-7.12) ^? fracLongitude :: Maybe Longitude
+-- Just (Longitude (DegreesLongitude (-7)) (Minutes 7) (Seconds 12.0000))
 --
--- >>> 3.15 ^? radianLongitude
+-- >>> fmap (fracLongitude #) (7.12 ^? fracLongitude :: Maybe Longitude)
+-- Just 7.12
+--
+-- >>> fmap (fracLongitude #) ((-7.12) ^? fracLongitude :: Maybe Longitude)
+-- Just (-7.12)
+--
+-- >>> 180 ^? fracLongitude :: Maybe Longitude
 -- Nothing
 --
--- >>> (-3.15) ^? radianLongitude
+-- >>> (-180) ^? fracLongitude :: Maybe Longitude
 -- Nothing
 --
--- >>> fmap (radianLongitude #) (do deg <- 7 ^? nDegreesLongitude; min <- 7 ^? nMinutes; sec <- 7 ^? nSeconds; (deg, min, sec) ^? dmsLongitude)
--- Just 0.12424320205794079
+-- >>> 15.63791 ^? fracLongitude :: Maybe Longitude
+-- Just (Longitude (DegreesLongitude 15) (Minutes 38) (Seconds 16.4760))
 --
--- >>> fmap (radianLongitude #) (do deg <- 179 ^? nDegreesLongitude; min <- 15 ^? nMinutes; sec <- 6 ^? nSeconds; (deg, min, sec) ^? dmsLongitude)
--- Just 3.1285317730207023
-radianLongitude ::
-  Prism' Double Longitude
-radianLongitude =
-  iso (\n -> n * 180 / pi) (\n -> n * pi / 180) . fracLongitude
-
-class HasLongitude t where
-  longitude ::
-    Lens' t Longitude
-
-instance HasLongitude Longitude where
-  longitude =
-    id
+-- >>> 179.1 ^? fracLongitude :: Maybe Longitude
+-- Just (Longitude (DegreesLongitude 179) (Minutes 5) (Seconds 60.0000))
+--
+-- >>> 179.2 ^? fracLongitude :: Maybe Longitude
+-- Just (Longitude (DegreesLongitude 179) (Minutes 11) (Seconds 60.0000))
+--
+-- >>> fmap (fracLongitude #) (do deg <- (7 :: Int) ^? _DegreesLongitude; min <- (7 :: Int) ^? _Minutes; sec <- (7 :: Double) ^? _Seconds; (deg, min, sec) ^? _Longitude :: Maybe Longitude)
+-- Just 7.118611111111111
+--
+-- >>> fmap (fracLongitude #) (do deg <- (179 :: Int) ^? _DegreesLongitude; min <- (15 :: Int) ^? _Minutes; sec <- (6 :: Double) ^? _Seconds; (deg, min, sec) ^? _Longitude :: Maybe Longitude)
+-- Just 179.25166666666667
+instance AsFracLongitude Longitude where
+  fracLongitude =
+    prism' (\(Longitude d m s) ->
+      let p = fromIntegral (_DegreesLongitude # d :: Int)
+          q = (fromIntegral (_Minutes # m :: Int) / 60) + (_Seconds # s) / 3600
+      in (if p < 0 then (-) else (+)) p q)
+      (\x -> let (d, z) = properFraction x
+                 (m, s) = properFraction ((z :: Double) * 60)
+             in do d' <- (d :: Int) ^? _DegreesLongitude
+                   m' <- (abs m :: Int) ^? _Minutes
+                   s' <- (abs s * 60) ^? _Seconds
+                   return (Longitude d' m' s'))
 
-instance HasDegreesLongitude Longitude where
-  degreesLongitude =
+instance (p ~ (->), Functor f) => AsDegreesLongitude p f Longitude where
+  _DegreesLongitude =
     lens (\(Longitude d _ _) -> d) (\(Longitude _ m s) d -> Longitude d m s)
-
-instance HasMinutes Longitude where
-  minutes =
+    
+instance (p ~ (->), Functor f) => AsMinutes p f Longitude where
+  _Minutes =
     lens (\(Longitude _ m _) -> m) (\(Longitude d _ s) m -> Longitude d m s)
 
-instance HasSeconds Longitude where
-  seconds =
+instance (p ~ (->), Functor f) => AsSeconds p f Longitude where
+  _Seconds =
     lens (\(Longitude _ _ s) -> s) (\(Longitude d m _) s -> Longitude d m s)
diff --git a/src/Data/Geo/Coordinate/Minutes.hs b/src/Data/Geo/Coordinate/Minutes.hs
--- a/src/Data/Geo/Coordinate/Minutes.hs
+++ b/src/Data/Geo/Coordinate/Minutes.hs
@@ -1,14 +1,16 @@
 {-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FlexibleInstances #-}
 
 module Data.Geo.Coordinate.Minutes(
   Minutes
-, HasMinutes(..)
-, nMinutes
+, AsMinutes(..)
 , modMinutes
 ) where
 
+import Control.Applicative(Applicative)
 import Control.Category(Category(id))
-import Control.Lens(Prism', Lens', prism')
+import Control.Lens(Optic', Choice, prism')
 import Data.Bool((&&))
 import Data.Maybe(Maybe(Just, Nothing))
 import Data.Eq(Eq)
@@ -18,7 +20,7 @@
 import Prelude(Show)
 
 -- $setup
--- >>> import Control.Lens((#), (^?))
+-- >>> import Control.Lens((#), (^?), (^.))
 -- >>> import Data.Foldable(all)
 -- >>> import Prelude(Eq(..))
 
@@ -26,9 +28,39 @@
   Minutes Int
   deriving (Eq, Ord, Show)
 
--- | Construct minutes such that if the given value is out of bounds,
--- a modulus is taken to keep it within 0 inclusive and 59 inclusive.
+class AsMinutes p f s where
+  _Minutes ::
+    Optic' p f s Minutes
+
+instance AsMinutes p f Minutes where
+  _Minutes =
+    id
+
+-- | A prism on minutes to an integer between 0 and 59 inclusive.
 --
+-- >>> (7 :: Int) ^? _Minutes
+-- Just (Minutes 7)
+--
+-- >>> (0 :: Int) ^? _Minutes
+-- Just (Minutes 0)
+--
+-- >>> (59 :: Int) ^? _Minutes
+-- Just (Minutes 59)
+--
+-- >>> (60 :: Int) ^? _Minutes
+-- Nothing
+--
+-- prop> all (\m -> _Minutes # m == (n :: Int)) (n ^? _Minutes)
+instance (Choice p, Applicative f) => AsMinutes p f Int where
+  _Minutes =
+    prism'
+      (\(Minutes i) -> i)
+      (\i -> if i >= 0 && i < 60
+               then Just (Minutes i)
+               else Nothing)       
+
+-- | Setting a value `>= 60` will get that value `(`mod` 60)`.
+--
 -- >>> modMinutes 7
 -- Minutes 7
 --
@@ -38,45 +70,13 @@
 -- >>> modMinutes 60
 -- Minutes 0
 --
--- >>> modMinutes 61
+-- >>> modMinutes 1
 -- Minutes 1
 --
 -- >>> modMinutes 59
--- Minutes 59
+-- Minutes 59 
 modMinutes ::
   Int
   -> Minutes
 modMinutes x =
   Minutes (x `mod'` 60)
-
--- | A prism on minutes to an integer between 0 and 59 inclusive.
---
--- >>> 7 ^? nMinutes
--- Just (Minutes 7)
---
--- >>> 0 ^? nMinutes
--- Just (Minutes 0)
---
--- >>> 59 ^? nMinutes
--- Just (Minutes 59)
---
--- >>> 60 ^? nMinutes
--- Nothing
---
--- prop> all (\m -> nMinutes # m == n) (n ^? nMinutes)
-nMinutes ::
-  Prism' Int Minutes
-nMinutes =
-  prism'
-    (\(Minutes i) -> i)
-    (\i -> if i >= 0 && i < 60
-             then Just (Minutes i)
-             else Nothing)
-
-class HasMinutes t where
-  minutes ::
-    Lens' t Minutes
-
-instance HasMinutes Minutes where
-  minutes =
-    id
diff --git a/src/Data/Geo/Coordinate/Seconds.hs b/src/Data/Geo/Coordinate/Seconds.hs
--- a/src/Data/Geo/Coordinate/Seconds.hs
+++ b/src/Data/Geo/Coordinate/Seconds.hs
@@ -1,14 +1,16 @@
 {-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FlexibleInstances #-}
 
 module Data.Geo.Coordinate.Seconds(
   Seconds
-, HasSeconds(..)
+, AsSeconds(..)
 , modSeconds
-, nSeconds
 ) where
 
+import Control.Applicative(Applicative)
 import Control.Category(Category(id))
-import Control.Lens(Prism', Lens', prism')
+import Control.Lens(prism', Optic', Choice)
 import Data.Bool((&&))
 import Data.Eq(Eq)
 import Data.Fixed(mod')
@@ -19,7 +21,7 @@
 import Text.Printf(printf)
 
 -- $setup
--- >>> import Control.Lens((#), (^?))
+-- >>> import Control.Lens((#), (^?), (^.))
 -- >>> import Data.Foldable(all)
 -- >>> import Prelude(Eq(..))
 
@@ -33,9 +35,42 @@
   showsPrec n (Seconds d) =
     showParen (n > 10) (showString ("Seconds " ++ printf "%0.4f" d))
 
--- | Construct seconds such that if the given value is out of bounds,
--- a modulus is taken to keep it within 0 inclusive and 60 exclusive.
+class AsSeconds p f s where
+  _Seconds ::
+    Optic' p f s Seconds
+
+instance AsSeconds p f Seconds where
+  _Seconds =
+    id
+
+-- | A prism on seconds to a double between 0 inclusive and 60 exclusive.
 --
+-- >>> (7 :: Double) ^? _Seconds
+-- Just (Seconds 7.0000)
+--
+-- >>> (0 :: Double) ^? _Seconds
+-- Just (Seconds 0.0000)
+--
+-- >>> (59 :: Double) ^? _Seconds
+-- Just (Seconds 59.0000)
+--
+-- >>> (59.99 :: Double) ^? _Seconds
+-- Just (Seconds 59.9900)
+--
+-- >>> (60 :: Double) ^? _Seconds
+-- Nothing
+--
+-- prop> all (\m -> _Seconds # m == (n :: Double)) (n ^? _Seconds)
+instance (Choice p, Applicative f) => AsSeconds p f Double where
+  _Seconds =
+    prism'
+      (\(Seconds d) -> d)
+      (\d -> if d >= 0 && d < 60
+               then Just (Seconds d)
+               else Nothing)
+
+-- | Setting a value `>= 60` will get that value `(`mod` 60)`.
+--
 -- >>> modSeconds 7
 -- Seconds 7.0000
 --
@@ -58,38 +93,3 @@
   -> Seconds
 modSeconds x =
   Seconds (x `mod'` 60)
-
--- | A prism on seconds to a double between 0 inclusive and 60 exclusive.
---
--- >>> 7 ^? nSeconds
--- Just (Seconds 7.0000)
---
--- >>> 0 ^? nSeconds
--- Just (Seconds 0.0000)
---
--- >>> 59 ^? nSeconds
--- Just (Seconds 59.0000)
---
--- >>> 59.99 ^? nSeconds
--- Just (Seconds 59.9900)
---
--- >>> 60 ^? nSeconds
--- Nothing
---
--- prop> all (\m -> nSeconds # m == n) (n ^? nSeconds)
-nSeconds ::
-  Prism' Double Seconds
-nSeconds =
-  prism'
-    (\(Seconds d) -> d)
-    (\d -> if d >= 0 && d < 60
-             then Just (Seconds d)
-             else Nothing)
-
-class HasSeconds t where
-  seconds ::
-    Lens' t Seconds
-
-instance HasSeconds Seconds where
-  seconds =
-    id
