packages feed

coordinate 0.0.3 → 0.0.4

raw patch · 17 files changed

+530/−530 lines, 17 files

Files

coordinate.cabal view
@@ -1,5 +1,5 @@ name:               coordinate-version:            0.0.3+version:            0.0.4 license:            BSD3 license-File:       etc/LICENCE author:             Tony Morris <ʇǝu˙sıɹɹoɯʇ@ןןǝʞsɐɥ>@@ -38,14 +38,14 @@                     src    exposed-modules:-                    Data.GPS.Coordinate-                    Data.GPS.Coordinate.Coordinate-                    Data.GPS.Coordinate.DegreesLatitude-                    Data.GPS.Coordinate.DegreesLongitude-                    Data.GPS.Coordinate.Latitude-                    Data.GPS.Coordinate.Longitude-                    Data.GPS.Coordinate.Minutes-                    Data.GPS.Coordinate.Seconds+                    Data.Geo.Coordinate+                    Data.Geo.Coordinate.Coordinate+                    Data.Geo.Coordinate.DegreesLatitude+                    Data.Geo.Coordinate.DegreesLongitude+                    Data.Geo.Coordinate.Latitude+                    Data.Geo.Coordinate.Longitude+                    Data.Geo.Coordinate.Minutes+                    Data.Geo.Coordinate.Seconds  test-suite doctests   type:
− src/Data/GPS/Coordinate.hs
@@ -1,9 +0,0 @@-module Data.GPS.Coordinate(module C) where--import Data.GPS.Coordinate.Coordinate as C-import Data.GPS.Coordinate.DegreesLatitude as C-import Data.GPS.Coordinate.DegreesLongitude as C-import Data.GPS.Coordinate.Latitude as C-import Data.GPS.Coordinate.Longitude as C-import Data.GPS.Coordinate.Minutes as C-import Data.GPS.Coordinate.Seconds as C
− src/Data/GPS/Coordinate/Coordinate.hs
@@ -1,74 +0,0 @@-module Data.GPS.Coordinate.Coordinate(-  Coordinate-, HasCoordinate(..)-, coordinateLatLon-, coordinateLonLat-, coordinateDMSLatLon-, coordinateLatDMSLon-, coordinateDMSLatDMSLon-) where--import Prelude(Eq, Show, Ord, id, (.))-import Control.Lens(Iso', Lens', iso, lens, mapping, swapped, withIso)-import Data.GPS.Coordinate.Latitude-import Data.GPS.Coordinate.Longitude-import Data.GPS.Coordinate.DegreesLatitude-import Data.GPS.Coordinate.DegreesLongitude-import Data.GPS.Coordinate.Minutes-import Data.GPS.Coordinate.Seconds--data Coordinate =-  Coordinate-    Latitude-    Longitude-  deriving (Eq, Ord, Show)--coordinateLatLon ::-  Iso' (Latitude, Longitude) Coordinate-coordinateLatLon =-  iso (\(lat, lon) -> Coordinate lat lon) (\(Coordinate lat lon) -> (lat, lon))--coordinateLonLat ::-  Iso' (Longitude, Latitude) Coordinate-coordinateLonLat =-  swapped . coordinateLatLon--coordinateDMSLatLon ::-  Iso' ((DegreesLatitude, Minutes, Seconds), Longitude) Coordinate-coordinateDMSLatLon =-  swapped . mapping dmsLatitude . coordinateLonLat--coordinateLatDMSLon ::-  Iso' (Latitude, (DegreesLongitude, Minutes, Seconds)) Coordinate-coordinateLatDMSLon =-  mapping dmsLongitude . coordinateLatLon--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)))--class HasCoordinate t where-  coordinate ::-    Lens' t Coordinate--instance HasCoordinate Coordinate where-  coordinate =-    id--instance HasLatitude Coordinate where-  latitude =-    lens (\(Coordinate lat _) -> lat) (\(Coordinate _ lon) lat -> Coordinate lat lon)--instance HasLongitude Coordinate where-  longitude =-    lens (\(Coordinate _ lon) -> lon) (\(Coordinate lat _) lon -> Coordinate lat lon)--instance HasDegreesLatitude Coordinate where-  degreesLatitude =-    latitude . degreesLatitude--instance HasDegreesLongitude Coordinate where-  degreesLongitude =-    longitude . degreesLongitude
− src/Data/GPS/Coordinate/DegreesLatitude.hs
@@ -1,57 +0,0 @@-module Data.GPS.Coordinate.DegreesLatitude(-  DegreesLatitude-, HasDegreesLatitude(..)-, nDegreesLatitude-) where--import Prelude(Int, Bool(..), Eq, Show, Ord(..), id, (&&))-import Data.Maybe(Maybe(..))-import Control.Lens(Prism', Lens', prism')---- $setup--- >>> import Control.Lens((#), (^?))--- >>> import Data.Foldable(all)--- >>> import Prelude(Eq(..))--newtype DegreesLatitude =-  DegreesLatitude Int-  deriving (Eq, Ord, Show)---- | A prism on degrees latitude to an integer between -90 and 90 exclusive.------ >>> 7 ^? nDegreesLatitude--- Just (DegreesLatitude 7)------ >>> 0 ^? nDegreesLatitude--- Just (DegreesLatitude 0)------ >>> 89 ^? nDegreesLatitude--- Just (DegreesLatitude 89)------ >>> 90 ^? nDegreesLatitude--- Nothing------ >>> (-89) ^? nDegreesLatitude--- Just (DegreesLatitude (-89))------ >>> (-90) ^? nDegreesLatitude--- Nothing------ prop> all (\m -> nDegreesLatitude # m == n) (n ^? nDegreesLatitude)-nDegreesLatitude ::-  Prism' Int DegreesLatitude-nDegreesLatitude =-  prism'-    (\(DegreesLatitude i) -> i)-    (\i -> case i > -90 && i < 90 of-             True -> Just (DegreesLatitude i)-             False -> Nothing)--class HasDegreesLatitude t where-  degreesLatitude ::-    Lens' t DegreesLatitude--instance HasDegreesLatitude DegreesLatitude where-  degreesLatitude =-    id-
− src/Data/GPS/Coordinate/DegreesLongitude.hs
@@ -1,56 +0,0 @@-module Data.GPS.Coordinate.DegreesLongitude(-  DegreesLongitude-, HasDegreesLongitude(..)-, nDegreesLongitude-) where--import Prelude(Int, Bool(..), Eq, Show, Ord(..), id, (&&))-import Data.Maybe(Maybe(..))-import Control.Lens(Prism', Lens', prism')---- $setup--- >>> import Control.Lens((#), (^?))--- >>> import Data.Foldable(all)--- >>> import Prelude(Eq(..))--newtype DegreesLongitude =-  DegreesLongitude Int-  deriving (Eq, Ord, Show)---- | A prism on degrees longitude to an integer between -180 and 180 exclusive.------ >>> 7 ^? nDegreesLongitude--- Just (DegreesLongitude 7)------ >>> 0 ^? nDegreesLongitude--- Just (DegreesLongitude 0)------ >>> 179 ^? nDegreesLongitude--- Just (DegreesLongitude 179)------ >>> 180 ^? nDegreesLongitude--- Nothing------ >>> (-179) ^? nDegreesLongitude--- Just (DegreesLongitude (-179))------ >>> (-180) ^? nDegreesLongitude--- Nothing------ prop> all (\m -> nDegreesLongitude # m == n) (n ^? nDegreesLongitude)-nDegreesLongitude ::-  Prism' Int DegreesLongitude-nDegreesLongitude  =-  prism'-    (\(DegreesLongitude i) -> i)-    (\i -> case i > -180 && i < 180 of-             True -> Just (DegreesLongitude i)-             False -> Nothing)--class HasDegreesLongitude t where-  degreesLongitude ::-    Lens' t DegreesLongitude--instance HasDegreesLongitude DegreesLongitude where-  degreesLongitude =-    id
− src/Data/GPS/Coordinate/Latitude.hs
@@ -1,109 +0,0 @@-module Data.GPS.Coordinate.Latitude(-  Latitude-, HasLatitude(..)-, dmsLatitude-, fracLatitude-) where--import Prelude(Double, Eq, Show, Ord(..), Num(..), Bool(..), Monad(..), id, (&&), properFraction, fromIntegral)-import Control.Lens(Iso', Prism', Lens', iso, prism', lens, (#), (^?))-import Data.GPS.Coordinate.DegreesLatitude-import Data.GPS.Coordinate.Minutes-import Data.GPS.Coordinate.Seconds---- $setup--- >>> import Control.Lens((^?))--data Latitude =-  Latitude-    DegreesLatitude-    Minutes-    Seconds-  deriving (Eq, Ord, Show)---- | 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--- Just (Latitude (DegreesLatitude 7) (Minutes 7) (Seconds 7.0000))------ >>> do deg <- 89 ^? nDegreesLatitude; min <- 59 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLatitude--- Just (Latitude (DegreesLatitude 89) (Minutes 59) (Seconds 59.0000))------ >>> do deg <- (-7) ^? nDegreesLatitude; min <- 7 ^? nMinutes; sec <- 7 ^? nSeconds; (deg, min, sec) ^? dmsLatitude--- Just (Latitude (DegreesLatitude (-7)) (Minutes 7) (Seconds 7.0000))------ >>> do deg <- (-89) ^? nDegreesLatitude; min <- 59 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLatitude--- Just (Latitude (DegreesLatitude (-89)) (Minutes 59) (Seconds 59.0000))------ >>> do deg <- 90 ^? nDegreesLatitude; min <- 59 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLatitude--- Nothing------ >>> do deg <- 89 ^? nDegreesLatitude; min <- 60 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLatitude--- Nothing------ >>> do deg <- 89 ^? nDegreesLatitude; min <- 59 ^? nMinutes; sec <- 60 ^? nSeconds; (deg, min, sec) ^? dmsLatitude--- Nothing-dmsLatitude ::-  Iso' (DegreesLatitude, Minutes, Seconds) Latitude-dmsLatitude =-  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 inclusive.------ >>> 7 ^? fracLatitude--- Just (Latitude (DegreesLatitude 7) (Minutes 0) (Seconds 0.0000))------ >>> (-7) ^? fracLatitude--- Just (Latitude (DegreesLatitude (-7)) (Minutes 0) (Seconds 0.0000))------ >>> 7.12 ^? fracLatitude--- Just (Latitude (DegreesLatitude 7) (Minutes 7) (Seconds 12.0000))------ >>> (-7.12) ^? fracLatitude--- Just (Latitude (DegreesLatitude (-7)) (Minutes 7) (Seconds 12.0000))------ >>> 90 ^? fracLatitude--- Nothing------ >>> (-90) ^? fracLatitude--- Nothing------ >>> 15.63791 ^? fracLatitude--- Just (Latitude (DegreesLatitude 15) (Minutes 38) (Seconds 16.4760))------ >>> 89.1 ^? fracLatitude--- Just (Latitude (DegreesLatitude 89) (Minutes 5) (Seconds 60.0000))------ >>> 89.2 ^? fracLatitude--- Just (Latitude (DegreesLatitude 89) (Minutes 12) (Seconds 0.0000))-fracLatitude ::-  Prism' Double Latitude-fracLatitude =-  prism' (\(Latitude d m s) ->-    fromIntegral (nDegreesLatitude # d) + nSeconds # s + fromIntegral (nMinutes # m * 60))-    (\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-                 return (Latitude d' m' s'))--class HasLatitude t where-  latitude ::-    Lens' t Latitude--instance HasLatitude Latitude where-  latitude =-    id--instance HasDegreesLatitude Latitude where-  degreesLatitude =-    lens (\(Latitude d _ _) -> d) (\(Latitude _ m s) d -> Latitude d m s)--instance HasMinutes Latitude where-  minutes =-    lens (\(Latitude _ m _) -> m) (\(Latitude d _ s) m -> Latitude d m s)--instance HasSeconds Latitude where-  seconds =-    lens (\(Latitude _ _ s) -> s) (\(Latitude d m _) s -> Latitude d m s)
− src/Data/GPS/Coordinate/Longitude.hs
@@ -1,106 +0,0 @@-module Data.GPS.Coordinate.Longitude(-  Longitude-, HasLongitude(..)-, dmsLongitude-, fracLongitude-) where--import Prelude(Double, Eq, Show, Ord(..), Num(..), Bool(..), Monad(..), id, (&&), properFraction, fromIntegral)-import Control.Lens(Iso', Prism', Lens', iso, prism', lens, (#), (^?))-import Data.GPS.Coordinate.DegreesLongitude-import Data.GPS.Coordinate.Minutes-import Data.GPS.Coordinate.Seconds--data Longitude =-  Longitude-    DegreesLongitude-    Minutes-    Seconds-  deriving (Eq, Ord, Show)---- | 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--- Just (Longitude (DegreesLongitude 7) (Minutes 7) (Seconds 7.0000))------ >>> do deg <- 179 ^? nDegreesLongitude; min <- 59 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLongitude--- Just (Longitude (DegreesLongitude 179) (Minutes 59) (Seconds 59.0000))------ >>> do deg <- (-7) ^? nDegreesLongitude; min <- 7 ^? nMinutes; sec <- 7 ^? nSeconds; (deg, min, sec) ^? dmsLongitude--- Just (Longitude (DegreesLongitude (-7)) (Minutes 7) (Seconds 7.0000))------ >>> do deg <- (-179) ^? nDegreesLongitude; min <- 59 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLongitude--- Just (Longitude (DegreesLongitude (-179)) (Minutes 59) (Seconds 59.0000))------ >>> do deg <- 180 ^? nDegreesLongitude; min <- 59 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLongitude--- Nothing------ >>> do deg <- 179 ^? nDegreesLongitude; min <- 60 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLongitude--- Nothing------ >>> do deg <- 179 ^? nDegreesLongitude; min <- 59 ^? nMinutes; sec <- 60 ^? nSeconds; (deg, min, sec) ^? dmsLongitude--- Nothing-dmsLongitude ::-  Iso' (DegreesLongitude, Minutes, Seconds) Longitude-dmsLongitude =-  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 inclusive.------ >>> 7 ^? fracLongitude--- Just (Longitude (DegreesLongitude 7) (Minutes 0) (Seconds 0.0000))------ >>> (-7) ^? fracLongitude--- Just (Longitude (DegreesLongitude (-7)) (Minutes 0) (Seconds 0.0000))------ >>> 7.12 ^? fracLongitude--- Just (Longitude (DegreesLongitude 7) (Minutes 7) (Seconds 12.0000))------ >>> (-7.12) ^? fracLongitude--- Just (Longitude (DegreesLongitude (-7)) (Minutes 7) (Seconds 12.0000))------ >>> 180 ^? fracLongitude--- Nothing------ >>> (-180) ^? fracLongitude--- Nothing------ >>> 15.63791 ^? fracLongitude--- Just (Longitude (DegreesLongitude 15) (Minutes 38) (Seconds 16.4760))------ >>> 179.1 ^? fracLongitude--- Just (Longitude (DegreesLongitude 179) (Minutes 5) (Seconds 60.0000))------ >>> 179.2 ^? fracLongitude--- Just (Longitude (DegreesLongitude 179) (Minutes 11) (Seconds 60.0000))-fracLongitude ::-  Prism' Double Longitude-fracLongitude =-  prism' (\(Longitude d m s) ->-    fromIntegral (nDegreesLongitude  # d) + nSeconds # s + fromIntegral (nMinutes # m * 60))-    (\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'))--class HasLongitude t where-  longitude ::-    Lens' t Longitude--instance HasLongitude Longitude where-  longitude =-    id--instance HasDegreesLongitude Longitude where-  degreesLongitude =-    lens (\(Longitude d _ _) -> d) (\(Longitude _ m s) d -> Longitude d m s)--instance HasMinutes Longitude where-  minutes =-    lens (\(Longitude _ m _) -> m) (\(Longitude d _ s) m -> Longitude d m s)--instance HasSeconds Longitude where-  seconds =-    lens (\(Longitude _ _ s) -> s) (\(Longitude d m _) s -> Longitude d m s)
− src/Data/GPS/Coordinate/Minutes.hs
@@ -1,50 +0,0 @@-module Data.GPS.Coordinate.Minutes(-  Minutes-, HasMinutes(..)-, nMinutes-) where--import Prelude(Functor, Int, Bool(..), Eq, Show, Ord(..), (&&), id)-import Data.Maybe(Maybe(..))-import Control.Lens(Prism', Lens', prism')---- $setup--- >>> import Control.Lens((#), (^?))--- >>> import Data.Foldable(all)--- >>> import Prelude(Eq(..))--newtype Minutes =-  Minutes Int-  deriving (Eq, Ord, Show)---- | 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 -> case i >= 0 && i < 60 of-             True -> Just (Minutes i)-             False -> Nothing)--class HasMinutes t where-  minutes ::-    Lens' t Minutes--instance HasMinutes Minutes where-  minutes =-    id
− src/Data/GPS/Coordinate/Seconds.hs
@@ -1,60 +0,0 @@-module Data.GPS.Coordinate.Seconds(-  Seconds-, HasSeconds(..)-, nSeconds-) where--import Prelude(Double, Bool(..), Eq, Show(..), Ord(..), id, (&&), (++), showParen, showString)-import Data.Maybe(Maybe(..))-import Control.Lens(Prism', Lens', prism')-import Text.Printf(printf)---- $setup--- >>> import Control.Lens((#), (^?))--- >>> import Data.Foldable(all)--- >>> import Prelude(Eq(..))--newtype Seconds =-  Seconds Double-  deriving (Eq, Ord)---- | A show instance that prints to 4 decimal places.--- This is to take floating-point rounding errors into account.-instance Show Seconds where-  showsPrec n (Seconds d) =-    showParen (n > 10) (showString ("Seconds " ++ printf "%0.4f" d))---- | 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 -> case d >= 0 && d < 60 of-             True -> Just (Seconds d)-             False -> Nothing)--class HasSeconds t where-  seconds ::-    Lens' t Seconds--instance HasSeconds Seconds where-  seconds =-    id
+ src/Data/Geo/Coordinate.hs view
@@ -0,0 +1,9 @@+module Data.Geo.Coordinate(module C) where++import Data.Geo.Coordinate.Coordinate as C+import Data.Geo.Coordinate.DegreesLatitude as C+import Data.Geo.Coordinate.DegreesLongitude as C+import Data.Geo.Coordinate.Latitude as C+import Data.Geo.Coordinate.Longitude as C+import Data.Geo.Coordinate.Minutes as C+import Data.Geo.Coordinate.Seconds as C
+ src/Data/Geo/Coordinate/Coordinate.hs view
@@ -0,0 +1,74 @@+module Data.Geo.Coordinate.Coordinate(+  Coordinate+, HasCoordinate(..)+, coordinateLatLon+, coordinateLonLat+, coordinateDMSLatLon+, coordinateLatDMSLon+, coordinateDMSLatDMSLon+) where++import Prelude(Eq, Show, Ord, id, (.))+import Control.Lens(Iso', Lens', iso, lens, mapping, swapped, withIso)+import Data.Geo.Coordinate.Latitude+import Data.Geo.Coordinate.Longitude+import Data.Geo.Coordinate.DegreesLatitude+import Data.Geo.Coordinate.DegreesLongitude+import Data.Geo.Coordinate.Minutes+import Data.Geo.Coordinate.Seconds++data Coordinate =+  Coordinate+    Latitude+    Longitude+  deriving (Eq, Ord, Show)++coordinateLatLon ::+  Iso' (Latitude, Longitude) Coordinate+coordinateLatLon =+  iso (\(lat, lon) -> Coordinate lat lon) (\(Coordinate lat lon) -> (lat, lon))++coordinateLonLat ::+  Iso' (Longitude, Latitude) Coordinate+coordinateLonLat =+  swapped . coordinateLatLon++coordinateDMSLatLon ::+  Iso' ((DegreesLatitude, Minutes, Seconds), Longitude) Coordinate+coordinateDMSLatLon =+  swapped . mapping dmsLatitude . coordinateLonLat++coordinateLatDMSLon ::+  Iso' (Latitude, (DegreesLongitude, Minutes, Seconds)) Coordinate+coordinateLatDMSLon =+  mapping dmsLongitude . coordinateLatLon++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)))++class HasCoordinate t where+  coordinate ::+    Lens' t Coordinate++instance HasCoordinate Coordinate where+  coordinate =+    id++instance HasLatitude Coordinate where+  latitude =+    lens (\(Coordinate lat _) -> lat) (\(Coordinate _ lon) lat -> Coordinate lat lon)++instance HasLongitude Coordinate where+  longitude =+    lens (\(Coordinate _ lon) -> lon) (\(Coordinate lat _) lon -> Coordinate lat lon)++instance HasDegreesLatitude Coordinate where+  degreesLatitude =+    latitude . degreesLatitude++instance HasDegreesLongitude Coordinate where+  degreesLongitude =+    longitude . degreesLongitude
+ src/Data/Geo/Coordinate/DegreesLatitude.hs view
@@ -0,0 +1,57 @@+module Data.Geo.Coordinate.DegreesLatitude(+  DegreesLatitude+, HasDegreesLatitude(..)+, nDegreesLatitude+) where++import Prelude(Int, Bool(..), Eq, Show, Ord(..), id, (&&))+import Data.Maybe(Maybe(..))+import Control.Lens(Prism', Lens', prism')++-- $setup+-- >>> import Control.Lens((#), (^?))+-- >>> import Data.Foldable(all)+-- >>> import Prelude(Eq(..))++newtype DegreesLatitude =+  DegreesLatitude Int+  deriving (Eq, Ord, Show)++-- | A prism on degrees latitude to an integer between -90 and 90 exclusive.+--+-- >>> 7 ^? nDegreesLatitude+-- Just (DegreesLatitude 7)+--+-- >>> 0 ^? nDegreesLatitude+-- Just (DegreesLatitude 0)+--+-- >>> 89 ^? nDegreesLatitude+-- Just (DegreesLatitude 89)+--+-- >>> 90 ^? nDegreesLatitude+-- Nothing+--+-- >>> (-89) ^? nDegreesLatitude+-- Just (DegreesLatitude (-89))+--+-- >>> (-90) ^? nDegreesLatitude+-- Nothing+--+-- prop> all (\m -> nDegreesLatitude # m == n) (n ^? nDegreesLatitude)+nDegreesLatitude ::+  Prism' Int DegreesLatitude+nDegreesLatitude =+  prism'+    (\(DegreesLatitude i) -> i)+    (\i -> case i > -90 && i < 90 of+             True -> Just (DegreesLatitude i)+             False -> Nothing)++class HasDegreesLatitude t where+  degreesLatitude ::+    Lens' t DegreesLatitude++instance HasDegreesLatitude DegreesLatitude where+  degreesLatitude =+    id+
+ src/Data/Geo/Coordinate/DegreesLongitude.hs view
@@ -0,0 +1,56 @@+module Data.Geo.Coordinate.DegreesLongitude(+  DegreesLongitude+, HasDegreesLongitude(..)+, nDegreesLongitude+) where++import Prelude(Int, Bool(..), Eq, Show, Ord(..), id, (&&))+import Data.Maybe(Maybe(..))+import Control.Lens(Prism', Lens', prism')++-- $setup+-- >>> import Control.Lens((#), (^?))+-- >>> import Data.Foldable(all)+-- >>> import Prelude(Eq(..))++newtype DegreesLongitude =+  DegreesLongitude Int+  deriving (Eq, Ord, Show)++-- | A prism on degrees longitude to an integer between -180 and 180 exclusive.+--+-- >>> 7 ^? nDegreesLongitude+-- Just (DegreesLongitude 7)+--+-- >>> 0 ^? nDegreesLongitude+-- Just (DegreesLongitude 0)+--+-- >>> 179 ^? nDegreesLongitude+-- Just (DegreesLongitude 179)+--+-- >>> 180 ^? nDegreesLongitude+-- Nothing+--+-- >>> (-179) ^? nDegreesLongitude+-- Just (DegreesLongitude (-179))+--+-- >>> (-180) ^? nDegreesLongitude+-- Nothing+--+-- prop> all (\m -> nDegreesLongitude # m == n) (n ^? nDegreesLongitude)+nDegreesLongitude ::+  Prism' Int DegreesLongitude+nDegreesLongitude  =+  prism'+    (\(DegreesLongitude i) -> i)+    (\i -> case i > -180 && i < 180 of+             True -> Just (DegreesLongitude i)+             False -> Nothing)++class HasDegreesLongitude t where+  degreesLongitude ::+    Lens' t DegreesLongitude++instance HasDegreesLongitude DegreesLongitude where+  degreesLongitude =+    id
+ src/Data/Geo/Coordinate/Latitude.hs view
@@ -0,0 +1,109 @@+module Data.Geo.Coordinate.Latitude(+  Latitude+, HasLatitude(..)+, dmsLatitude+, fracLatitude+) where++import Prelude(Double, Eq, Show, Ord(..), Num(..), Bool(..), Monad(..), id, (&&), properFraction, fromIntegral)+import Control.Lens(Iso', Prism', Lens', iso, prism', lens, (#), (^?))+import Data.Geo.Coordinate.DegreesLatitude+import Data.Geo.Coordinate.Minutes+import Data.Geo.Coordinate.Seconds++-- $setup+-- >>> import Control.Lens((^?))++data Latitude =+  Latitude+    DegreesLatitude+    Minutes+    Seconds+  deriving (Eq, Ord, Show)++-- | 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+-- Just (Latitude (DegreesLatitude 7) (Minutes 7) (Seconds 7.0000))+--+-- >>> do deg <- 89 ^? nDegreesLatitude; min <- 59 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLatitude+-- Just (Latitude (DegreesLatitude 89) (Minutes 59) (Seconds 59.0000))+--+-- >>> do deg <- (-7) ^? nDegreesLatitude; min <- 7 ^? nMinutes; sec <- 7 ^? nSeconds; (deg, min, sec) ^? dmsLatitude+-- Just (Latitude (DegreesLatitude (-7)) (Minutes 7) (Seconds 7.0000))+--+-- >>> do deg <- (-89) ^? nDegreesLatitude; min <- 59 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLatitude+-- Just (Latitude (DegreesLatitude (-89)) (Minutes 59) (Seconds 59.0000))+--+-- >>> do deg <- 90 ^? nDegreesLatitude; min <- 59 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLatitude+-- Nothing+--+-- >>> do deg <- 89 ^? nDegreesLatitude; min <- 60 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLatitude+-- Nothing+--+-- >>> do deg <- 89 ^? nDegreesLatitude; min <- 59 ^? nMinutes; sec <- 60 ^? nSeconds; (deg, min, sec) ^? dmsLatitude+-- Nothing+dmsLatitude ::+  Iso' (DegreesLatitude, Minutes, Seconds) Latitude+dmsLatitude =+  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 inclusive.+--+-- >>> 7 ^? fracLatitude+-- Just (Latitude (DegreesLatitude 7) (Minutes 0) (Seconds 0.0000))+--+-- >>> (-7) ^? fracLatitude+-- Just (Latitude (DegreesLatitude (-7)) (Minutes 0) (Seconds 0.0000))+--+-- >>> 7.12 ^? fracLatitude+-- Just (Latitude (DegreesLatitude 7) (Minutes 7) (Seconds 12.0000))+--+-- >>> (-7.12) ^? fracLatitude+-- Just (Latitude (DegreesLatitude (-7)) (Minutes 7) (Seconds 12.0000))+--+-- >>> 90 ^? fracLatitude+-- Nothing+--+-- >>> (-90) ^? fracLatitude+-- Nothing+--+-- >>> 15.63791 ^? fracLatitude+-- Just (Latitude (DegreesLatitude 15) (Minutes 38) (Seconds 16.4760))+--+-- >>> 89.1 ^? fracLatitude+-- Just (Latitude (DegreesLatitude 89) (Minutes 5) (Seconds 60.0000))+--+-- >>> 89.2 ^? fracLatitude+-- Just (Latitude (DegreesLatitude 89) (Minutes 12) (Seconds 0.0000))+fracLatitude ::+  Prism' Double Latitude+fracLatitude =+  prism' (\(Latitude d m s) ->+    fromIntegral (nDegreesLatitude # d) + nSeconds # s + fromIntegral (nMinutes # m * 60))+    (\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+                 return (Latitude d' m' s'))++class HasLatitude t where+  latitude ::+    Lens' t Latitude++instance HasLatitude Latitude where+  latitude =+    id++instance HasDegreesLatitude Latitude where+  degreesLatitude =+    lens (\(Latitude d _ _) -> d) (\(Latitude _ m s) d -> Latitude d m s)++instance HasMinutes Latitude where+  minutes =+    lens (\(Latitude _ m _) -> m) (\(Latitude d _ s) m -> Latitude d m s)++instance HasSeconds Latitude where+  seconds =+    lens (\(Latitude _ _ s) -> s) (\(Latitude d m _) s -> Latitude d m s)
+ src/Data/Geo/Coordinate/Longitude.hs view
@@ -0,0 +1,106 @@+module Data.Geo.Coordinate.Longitude(+  Longitude+, HasLongitude(..)+, dmsLongitude+, fracLongitude+) where++import Prelude(Double, Eq, Show, Ord(..), Num(..), Bool(..), Monad(..), id, (&&), properFraction, fromIntegral)+import Control.Lens(Iso', Prism', Lens', iso, prism', lens, (#), (^?))+import Data.Geo.Coordinate.DegreesLongitude+import Data.Geo.Coordinate.Minutes+import Data.Geo.Coordinate.Seconds++data Longitude =+  Longitude+    DegreesLongitude+    Minutes+    Seconds+  deriving (Eq, Ord, Show)++-- | 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+-- Just (Longitude (DegreesLongitude 7) (Minutes 7) (Seconds 7.0000))+--+-- >>> do deg <- 179 ^? nDegreesLongitude; min <- 59 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLongitude+-- Just (Longitude (DegreesLongitude 179) (Minutes 59) (Seconds 59.0000))+--+-- >>> do deg <- (-7) ^? nDegreesLongitude; min <- 7 ^? nMinutes; sec <- 7 ^? nSeconds; (deg, min, sec) ^? dmsLongitude+-- Just (Longitude (DegreesLongitude (-7)) (Minutes 7) (Seconds 7.0000))+--+-- >>> do deg <- (-179) ^? nDegreesLongitude; min <- 59 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLongitude+-- Just (Longitude (DegreesLongitude (-179)) (Minutes 59) (Seconds 59.0000))+--+-- >>> do deg <- 180 ^? nDegreesLongitude; min <- 59 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLongitude+-- Nothing+--+-- >>> do deg <- 179 ^? nDegreesLongitude; min <- 60 ^? nMinutes; sec <- 59 ^? nSeconds; (deg, min, sec) ^? dmsLongitude+-- Nothing+--+-- >>> do deg <- 179 ^? nDegreesLongitude; min <- 59 ^? nMinutes; sec <- 60 ^? nSeconds; (deg, min, sec) ^? dmsLongitude+-- Nothing+dmsLongitude ::+  Iso' (DegreesLongitude, Minutes, Seconds) Longitude+dmsLongitude =+  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 inclusive.+--+-- >>> 7 ^? fracLongitude+-- Just (Longitude (DegreesLongitude 7) (Minutes 0) (Seconds 0.0000))+--+-- >>> (-7) ^? fracLongitude+-- Just (Longitude (DegreesLongitude (-7)) (Minutes 0) (Seconds 0.0000))+--+-- >>> 7.12 ^? fracLongitude+-- Just (Longitude (DegreesLongitude 7) (Minutes 7) (Seconds 12.0000))+--+-- >>> (-7.12) ^? fracLongitude+-- Just (Longitude (DegreesLongitude (-7)) (Minutes 7) (Seconds 12.0000))+--+-- >>> 180 ^? fracLongitude+-- Nothing+--+-- >>> (-180) ^? fracLongitude+-- Nothing+--+-- >>> 15.63791 ^? fracLongitude+-- Just (Longitude (DegreesLongitude 15) (Minutes 38) (Seconds 16.4760))+--+-- >>> 179.1 ^? fracLongitude+-- Just (Longitude (DegreesLongitude 179) (Minutes 5) (Seconds 60.0000))+--+-- >>> 179.2 ^? fracLongitude+-- Just (Longitude (DegreesLongitude 179) (Minutes 11) (Seconds 60.0000))+fracLongitude ::+  Prism' Double Longitude+fracLongitude =+  prism' (\(Longitude d m s) ->+    fromIntegral (nDegreesLongitude  # d) + nSeconds # s + fromIntegral (nMinutes # m * 60))+    (\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'))++class HasLongitude t where+  longitude ::+    Lens' t Longitude++instance HasLongitude Longitude where+  longitude =+    id++instance HasDegreesLongitude Longitude where+  degreesLongitude =+    lens (\(Longitude d _ _) -> d) (\(Longitude _ m s) d -> Longitude d m s)++instance HasMinutes Longitude where+  minutes =+    lens (\(Longitude _ m _) -> m) (\(Longitude d _ s) m -> Longitude d m s)++instance HasSeconds Longitude where+  seconds =+    lens (\(Longitude _ _ s) -> s) (\(Longitude d m _) s -> Longitude d m s)
+ src/Data/Geo/Coordinate/Minutes.hs view
@@ -0,0 +1,50 @@+module Data.Geo.Coordinate.Minutes(+  Minutes+, HasMinutes(..)+, nMinutes+) where++import Prelude(Functor, Int, Bool(..), Eq, Show, Ord(..), (&&), id)+import Data.Maybe(Maybe(..))+import Control.Lens(Prism', Lens', prism')++-- $setup+-- >>> import Control.Lens((#), (^?))+-- >>> import Data.Foldable(all)+-- >>> import Prelude(Eq(..))++newtype Minutes =+  Minutes Int+  deriving (Eq, Ord, Show)++-- | 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 -> case i >= 0 && i < 60 of+             True -> Just (Minutes i)+             False -> Nothing)++class HasMinutes t where+  minutes ::+    Lens' t Minutes++instance HasMinutes Minutes where+  minutes =+    id
+ src/Data/Geo/Coordinate/Seconds.hs view
@@ -0,0 +1,60 @@+module Data.Geo.Coordinate.Seconds(+  Seconds+, HasSeconds(..)+, nSeconds+) where++import Prelude(Double, Bool(..), Eq, Show(..), Ord(..), id, (&&), (++), showParen, showString)+import Data.Maybe(Maybe(..))+import Control.Lens(Prism', Lens', prism')+import Text.Printf(printf)++-- $setup+-- >>> import Control.Lens((#), (^?))+-- >>> import Data.Foldable(all)+-- >>> import Prelude(Eq(..))++newtype Seconds =+  Seconds Double+  deriving (Eq, Ord)++-- | A show instance that prints to 4 decimal places.+-- This is to take floating-point rounding errors into account.+instance Show Seconds where+  showsPrec n (Seconds d) =+    showParen (n > 10) (showString ("Seconds " ++ printf "%0.4f" d))++-- | 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 -> case d >= 0 && d < 60 of+             True -> Just (Seconds d)+             False -> Nothing)++class HasSeconds t where+  seconds ::+    Lens' t Seconds++instance HasSeconds Seconds where+  seconds =+    id