{-|
Module: Data.Astro.Types
Description: Common Types
Copyright: Alexander Ignatyev, 2016

Common Types are usfull across all subsystems like Time and Coordinate.

= Examples

== /Decimal hours and Decimal degrees/

@
import Data.Astro.Types

-- 10h 15m 19.7s
dh :: DecimalHours
dh = fromHMS 10 15 19.7
-- DH 10.255472222222222

(h, m, s) = toHMS dh
-- (10,15,19.699999999999562)


-- 51°28′40″
dd :: DecimalDegrees
dd = fromDMS 51 28 40
-- DD 51.477777777777774

(d, m, s) = toDMS dd
-- (51,28,39.999999999987494)
@

== /Geographic Coordinates/
@
import Data.Astro.Types

-- the Royal Observatory, Greenwich
ro :: GeographicCoordinates
ro = GeoC (fromDMS 51 28 40) (-(fromDMS 0 0 5))
-- GeoC {geoLatitude = DD 51.4778, geoLongitude = DD (-0.0014)}
@
-}

module Data.Astro.Types
(
  DecimalDegrees(..)
  , DecimalHours (..)
  , GeographicCoordinates(..)
  , AstronomicalUnits(..)
  , lightTravelTime
  , kmToAU
  , auToKM
  , toDecimalHours
  , fromDecimalHours
  , toRadians
  , fromRadians
  , fromDMS
  , toDMS
  , fromHMS
  , toHMS
)

where

import qualified Data.Astro.Utils as U


newtype DecimalDegrees = DD Double
                         deriving (Int -> DecimalDegrees -> ShowS
[DecimalDegrees] -> ShowS
DecimalDegrees -> String
(Int -> DecimalDegrees -> ShowS)
-> (DecimalDegrees -> String)
-> ([DecimalDegrees] -> ShowS)
-> Show DecimalDegrees
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DecimalDegrees] -> ShowS
$cshowList :: [DecimalDegrees] -> ShowS
show :: DecimalDegrees -> String
$cshow :: DecimalDegrees -> String
showsPrec :: Int -> DecimalDegrees -> ShowS
$cshowsPrec :: Int -> DecimalDegrees -> ShowS
Show, DecimalDegrees -> DecimalDegrees -> Bool
(DecimalDegrees -> DecimalDegrees -> Bool)
-> (DecimalDegrees -> DecimalDegrees -> Bool) -> Eq DecimalDegrees
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DecimalDegrees -> DecimalDegrees -> Bool
$c/= :: DecimalDegrees -> DecimalDegrees -> Bool
== :: DecimalDegrees -> DecimalDegrees -> Bool
$c== :: DecimalDegrees -> DecimalDegrees -> Bool
Eq, Eq DecimalDegrees
Eq DecimalDegrees
-> (DecimalDegrees -> DecimalDegrees -> Ordering)
-> (DecimalDegrees -> DecimalDegrees -> Bool)
-> (DecimalDegrees -> DecimalDegrees -> Bool)
-> (DecimalDegrees -> DecimalDegrees -> Bool)
-> (DecimalDegrees -> DecimalDegrees -> Bool)
-> (DecimalDegrees -> DecimalDegrees -> DecimalDegrees)
-> (DecimalDegrees -> DecimalDegrees -> DecimalDegrees)
-> Ord DecimalDegrees
DecimalDegrees -> DecimalDegrees -> Bool
DecimalDegrees -> DecimalDegrees -> Ordering
DecimalDegrees -> DecimalDegrees -> DecimalDegrees
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: DecimalDegrees -> DecimalDegrees -> DecimalDegrees
$cmin :: DecimalDegrees -> DecimalDegrees -> DecimalDegrees
max :: DecimalDegrees -> DecimalDegrees -> DecimalDegrees
$cmax :: DecimalDegrees -> DecimalDegrees -> DecimalDegrees
>= :: DecimalDegrees -> DecimalDegrees -> Bool
$c>= :: DecimalDegrees -> DecimalDegrees -> Bool
> :: DecimalDegrees -> DecimalDegrees -> Bool
$c> :: DecimalDegrees -> DecimalDegrees -> Bool
<= :: DecimalDegrees -> DecimalDegrees -> Bool
$c<= :: DecimalDegrees -> DecimalDegrees -> Bool
< :: DecimalDegrees -> DecimalDegrees -> Bool
$c< :: DecimalDegrees -> DecimalDegrees -> Bool
compare :: DecimalDegrees -> DecimalDegrees -> Ordering
$ccompare :: DecimalDegrees -> DecimalDegrees -> Ordering
$cp1Ord :: Eq DecimalDegrees
Ord)


instance Num DecimalDegrees where
  + :: DecimalDegrees -> DecimalDegrees -> DecimalDegrees
(+) (DD Double
d1) (DD Double
d2) = Double -> DecimalDegrees
DD (Double
d1Double -> Double -> Double
forall a. Num a => a -> a -> a
+Double
d2)
  (-) (DD Double
d1) (DD Double
d2) = Double -> DecimalDegrees
DD (Double
d1Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
d2)
  * :: DecimalDegrees -> DecimalDegrees -> DecimalDegrees
(*) (DD Double
d1) (DD Double
d2) = Double -> DecimalDegrees
DD (Double
d1Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
d2)
  negate :: DecimalDegrees -> DecimalDegrees
negate (DD Double
d) = Double -> DecimalDegrees
DD (Double -> Double
forall a. Num a => a -> a
negate Double
d)
  abs :: DecimalDegrees -> DecimalDegrees
abs (DD Double
d) = Double -> DecimalDegrees
DD (Double -> Double
forall a. Num a => a -> a
abs Double
d)
  signum :: DecimalDegrees -> DecimalDegrees
signum (DD Double
d) = Double -> DecimalDegrees
DD (Double -> Double
forall a. Num a => a -> a
signum Double
d)
  fromInteger :: Integer -> DecimalDegrees
fromInteger Integer
int = Double -> DecimalDegrees
DD (Integer -> Double
forall a. Num a => Integer -> a
fromInteger Integer
int)

instance Real DecimalDegrees where
  toRational :: DecimalDegrees -> Rational
toRational (DD Double
d) = Double -> Rational
forall a. Real a => a -> Rational
toRational Double
d

instance Fractional DecimalDegrees where
  / :: DecimalDegrees -> DecimalDegrees -> DecimalDegrees
(/) (DD Double
d1) (DD Double
d2) = Double -> DecimalDegrees
DD (Double
d1Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
d2)
  recip :: DecimalDegrees -> DecimalDegrees
recip (DD Double
d) = Double -> DecimalDegrees
DD (Double -> Double
forall a. Fractional a => a -> a
recip Double
d)
  fromRational :: Rational -> DecimalDegrees
fromRational Rational
r = Double -> DecimalDegrees
DD (Rational -> Double
forall a. Fractional a => Rational -> a
fromRational Rational
r)

instance RealFrac DecimalDegrees where
  properFraction :: DecimalDegrees -> (b, DecimalDegrees)
properFraction (DD Double
d) =
    let (b
i, Double
f) = Double -> (b, Double)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction Double
d
    in (b
i, Double -> DecimalDegrees
DD Double
f)


newtype DecimalHours = DH Double
                       deriving (Int -> DecimalHours -> ShowS
[DecimalHours] -> ShowS
DecimalHours -> String
(Int -> DecimalHours -> ShowS)
-> (DecimalHours -> String)
-> ([DecimalHours] -> ShowS)
-> Show DecimalHours
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DecimalHours] -> ShowS
$cshowList :: [DecimalHours] -> ShowS
show :: DecimalHours -> String
$cshow :: DecimalHours -> String
showsPrec :: Int -> DecimalHours -> ShowS
$cshowsPrec :: Int -> DecimalHours -> ShowS
Show, DecimalHours -> DecimalHours -> Bool
(DecimalHours -> DecimalHours -> Bool)
-> (DecimalHours -> DecimalHours -> Bool) -> Eq DecimalHours
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DecimalHours -> DecimalHours -> Bool
$c/= :: DecimalHours -> DecimalHours -> Bool
== :: DecimalHours -> DecimalHours -> Bool
$c== :: DecimalHours -> DecimalHours -> Bool
Eq, Eq DecimalHours
Eq DecimalHours
-> (DecimalHours -> DecimalHours -> Ordering)
-> (DecimalHours -> DecimalHours -> Bool)
-> (DecimalHours -> DecimalHours -> Bool)
-> (DecimalHours -> DecimalHours -> Bool)
-> (DecimalHours -> DecimalHours -> Bool)
-> (DecimalHours -> DecimalHours -> DecimalHours)
-> (DecimalHours -> DecimalHours -> DecimalHours)
-> Ord DecimalHours
DecimalHours -> DecimalHours -> Bool
DecimalHours -> DecimalHours -> Ordering
DecimalHours -> DecimalHours -> DecimalHours
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: DecimalHours -> DecimalHours -> DecimalHours
$cmin :: DecimalHours -> DecimalHours -> DecimalHours
max :: DecimalHours -> DecimalHours -> DecimalHours
$cmax :: DecimalHours -> DecimalHours -> DecimalHours
>= :: DecimalHours -> DecimalHours -> Bool
$c>= :: DecimalHours -> DecimalHours -> Bool
> :: DecimalHours -> DecimalHours -> Bool
$c> :: DecimalHours -> DecimalHours -> Bool
<= :: DecimalHours -> DecimalHours -> Bool
$c<= :: DecimalHours -> DecimalHours -> Bool
< :: DecimalHours -> DecimalHours -> Bool
$c< :: DecimalHours -> DecimalHours -> Bool
compare :: DecimalHours -> DecimalHours -> Ordering
$ccompare :: DecimalHours -> DecimalHours -> Ordering
$cp1Ord :: Eq DecimalHours
Ord)


instance Num DecimalHours where
  + :: DecimalHours -> DecimalHours -> DecimalHours
(+) (DH Double
d1) (DH Double
d2) = Double -> DecimalHours
DH (Double
d1Double -> Double -> Double
forall a. Num a => a -> a -> a
+Double
d2)
  (-) (DH Double
d1) (DH Double
d2) = Double -> DecimalHours
DH (Double
d1Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
d2)
  * :: DecimalHours -> DecimalHours -> DecimalHours
(*) (DH Double
d1) (DH Double
d2) = Double -> DecimalHours
DH (Double
d1Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
d2)
  negate :: DecimalHours -> DecimalHours
negate (DH Double
d) = Double -> DecimalHours
DH (Double -> Double
forall a. Num a => a -> a
negate Double
d)
  abs :: DecimalHours -> DecimalHours
abs (DH Double
d) = Double -> DecimalHours
DH (Double -> Double
forall a. Num a => a -> a
abs Double
d)
  signum :: DecimalHours -> DecimalHours
signum (DH Double
d) = Double -> DecimalHours
DH (Double -> Double
forall a. Num a => a -> a
signum Double
d)
  fromInteger :: Integer -> DecimalHours
fromInteger Integer
int = Double -> DecimalHours
DH (Integer -> Double
forall a. Num a => Integer -> a
fromInteger Integer
int)

instance Real DecimalHours where
  toRational :: DecimalHours -> Rational
toRational (DH Double
d) = Double -> Rational
forall a. Real a => a -> Rational
toRational Double
d

instance Fractional DecimalHours where
  / :: DecimalHours -> DecimalHours -> DecimalHours
(/) (DH Double
d1) (DH Double
d2) = Double -> DecimalHours
DH (Double
d1Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
d2)
  recip :: DecimalHours -> DecimalHours
recip (DH Double
d) = Double -> DecimalHours
DH (Double -> Double
forall a. Fractional a => a -> a
recip Double
d)
  fromRational :: Rational -> DecimalHours
fromRational Rational
r = Double -> DecimalHours
DH (Rational -> Double
forall a. Fractional a => Rational -> a
fromRational Rational
r)

instance RealFrac DecimalHours where
  properFraction :: DecimalHours -> (b, DecimalHours)
properFraction (DH Double
d) =
    let (b
i, Double
f) = Double -> (b, Double)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction Double
d
    in (b
i, Double -> DecimalHours
DH Double
f)


-- | Convert decimal degrees to decimal hours

toDecimalHours :: DecimalDegrees -> DecimalHours
toDecimalHours :: DecimalDegrees -> DecimalHours
toDecimalHours (DD Double
d) = Double -> DecimalHours
DH (Double -> DecimalHours) -> Double -> DecimalHours
forall a b. (a -> b) -> a -> b
$ Double
dDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
15  -- 360 / 24 = 15


-- | Convert decimal hours to decimal degrees

fromDecimalHours :: DecimalHours -> DecimalDegrees
fromDecimalHours :: DecimalHours -> DecimalDegrees
fromDecimalHours (DH Double
h) = Double -> DecimalDegrees
DD (Double -> DecimalDegrees) -> Double -> DecimalDegrees
forall a b. (a -> b) -> a -> b
$ Double
hDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
15


-- | Geographic Coordinates

data GeographicCoordinates = GeoC {
  GeographicCoordinates -> DecimalDegrees
geoLatitude :: DecimalDegrees
  , GeographicCoordinates -> DecimalDegrees
geoLongitude :: DecimalDegrees
  } deriving (Int -> GeographicCoordinates -> ShowS
[GeographicCoordinates] -> ShowS
GeographicCoordinates -> String
(Int -> GeographicCoordinates -> ShowS)
-> (GeographicCoordinates -> String)
-> ([GeographicCoordinates] -> ShowS)
-> Show GeographicCoordinates
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [GeographicCoordinates] -> ShowS
$cshowList :: [GeographicCoordinates] -> ShowS
show :: GeographicCoordinates -> String
$cshow :: GeographicCoordinates -> String
showsPrec :: Int -> GeographicCoordinates -> ShowS
$cshowsPrec :: Int -> GeographicCoordinates -> ShowS
Show, GeographicCoordinates -> GeographicCoordinates -> Bool
(GeographicCoordinates -> GeographicCoordinates -> Bool)
-> (GeographicCoordinates -> GeographicCoordinates -> Bool)
-> Eq GeographicCoordinates
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: GeographicCoordinates -> GeographicCoordinates -> Bool
$c/= :: GeographicCoordinates -> GeographicCoordinates -> Bool
== :: GeographicCoordinates -> GeographicCoordinates -> Bool
$c== :: GeographicCoordinates -> GeographicCoordinates -> Bool
Eq)


-- | Astronomical Units, 1AU = 1.4960×1011 m

-- (originally, the average distance of Earth's aphelion and perihelion).

newtype AstronomicalUnits = AU Double deriving (Int -> AstronomicalUnits -> ShowS
[AstronomicalUnits] -> ShowS
AstronomicalUnits -> String
(Int -> AstronomicalUnits -> ShowS)
-> (AstronomicalUnits -> String)
-> ([AstronomicalUnits] -> ShowS)
-> Show AstronomicalUnits
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AstronomicalUnits] -> ShowS
$cshowList :: [AstronomicalUnits] -> ShowS
show :: AstronomicalUnits -> String
$cshow :: AstronomicalUnits -> String
showsPrec :: Int -> AstronomicalUnits -> ShowS
$cshowsPrec :: Int -> AstronomicalUnits -> ShowS
Show, AstronomicalUnits -> AstronomicalUnits -> Bool
(AstronomicalUnits -> AstronomicalUnits -> Bool)
-> (AstronomicalUnits -> AstronomicalUnits -> Bool)
-> Eq AstronomicalUnits
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AstronomicalUnits -> AstronomicalUnits -> Bool
$c/= :: AstronomicalUnits -> AstronomicalUnits -> Bool
== :: AstronomicalUnits -> AstronomicalUnits -> Bool
$c== :: AstronomicalUnits -> AstronomicalUnits -> Bool
Eq, Eq AstronomicalUnits
Eq AstronomicalUnits
-> (AstronomicalUnits -> AstronomicalUnits -> Ordering)
-> (AstronomicalUnits -> AstronomicalUnits -> Bool)
-> (AstronomicalUnits -> AstronomicalUnits -> Bool)
-> (AstronomicalUnits -> AstronomicalUnits -> Bool)
-> (AstronomicalUnits -> AstronomicalUnits -> Bool)
-> (AstronomicalUnits -> AstronomicalUnits -> AstronomicalUnits)
-> (AstronomicalUnits -> AstronomicalUnits -> AstronomicalUnits)
-> Ord AstronomicalUnits
AstronomicalUnits -> AstronomicalUnits -> Bool
AstronomicalUnits -> AstronomicalUnits -> Ordering
AstronomicalUnits -> AstronomicalUnits -> AstronomicalUnits
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: AstronomicalUnits -> AstronomicalUnits -> AstronomicalUnits
$cmin :: AstronomicalUnits -> AstronomicalUnits -> AstronomicalUnits
max :: AstronomicalUnits -> AstronomicalUnits -> AstronomicalUnits
$cmax :: AstronomicalUnits -> AstronomicalUnits -> AstronomicalUnits
>= :: AstronomicalUnits -> AstronomicalUnits -> Bool
$c>= :: AstronomicalUnits -> AstronomicalUnits -> Bool
> :: AstronomicalUnits -> AstronomicalUnits -> Bool
$c> :: AstronomicalUnits -> AstronomicalUnits -> Bool
<= :: AstronomicalUnits -> AstronomicalUnits -> Bool
$c<= :: AstronomicalUnits -> AstronomicalUnits -> Bool
< :: AstronomicalUnits -> AstronomicalUnits -> Bool
$c< :: AstronomicalUnits -> AstronomicalUnits -> Bool
compare :: AstronomicalUnits -> AstronomicalUnits -> Ordering
$ccompare :: AstronomicalUnits -> AstronomicalUnits -> Ordering
$cp1Ord :: Eq AstronomicalUnits
Ord)


instance Num AstronomicalUnits where
  + :: AstronomicalUnits -> AstronomicalUnits -> AstronomicalUnits
(+) (AU Double
d1) (AU Double
d2) = Double -> AstronomicalUnits
AU (Double
d1Double -> Double -> Double
forall a. Num a => a -> a -> a
+Double
d2)
  (-) (AU Double
d1) (AU Double
d2) = Double -> AstronomicalUnits
AU (Double
d1Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
d2)
  * :: AstronomicalUnits -> AstronomicalUnits -> AstronomicalUnits
(*) (AU Double
d1) (AU Double
d2) = Double -> AstronomicalUnits
AU (Double
d1Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
d2)
  negate :: AstronomicalUnits -> AstronomicalUnits
negate (AU Double
d) = Double -> AstronomicalUnits
AU (Double -> Double
forall a. Num a => a -> a
negate Double
d)
  abs :: AstronomicalUnits -> AstronomicalUnits
abs (AU Double
d) = Double -> AstronomicalUnits
AU (Double -> Double
forall a. Num a => a -> a
abs Double
d)
  signum :: AstronomicalUnits -> AstronomicalUnits
signum (AU Double
d) = Double -> AstronomicalUnits
AU (Double -> Double
forall a. Num a => a -> a
signum Double
d)
  fromInteger :: Integer -> AstronomicalUnits
fromInteger Integer
int = Double -> AstronomicalUnits
AU (Integer -> Double
forall a. Num a => Integer -> a
fromInteger Integer
int)

instance Real AstronomicalUnits where
  toRational :: AstronomicalUnits -> Rational
toRational (AU Double
d) = Double -> Rational
forall a. Real a => a -> Rational
toRational Double
d

instance Fractional AstronomicalUnits where
  / :: AstronomicalUnits -> AstronomicalUnits -> AstronomicalUnits
(/) (AU Double
d1) (AU Double
d2) = Double -> AstronomicalUnits
AU (Double
d1Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
d2)
  recip :: AstronomicalUnits -> AstronomicalUnits
recip (AU Double
d) = Double -> AstronomicalUnits
AU (Double -> Double
forall a. Fractional a => a -> a
recip Double
d)
  fromRational :: Rational -> AstronomicalUnits
fromRational Rational
r = Double -> AstronomicalUnits
AU (Rational -> Double
forall a. Fractional a => Rational -> a
fromRational Rational
r)

instance RealFrac AstronomicalUnits where
  properFraction :: AstronomicalUnits -> (b, AstronomicalUnits)
properFraction (AU Double
d) =
    let (b
i, Double
f) = Double -> (b, Double)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction Double
d
    in (b
i, Double -> AstronomicalUnits
AU Double
f)


-- | Light travel time of the distance in Astronomical Units

lightTravelTime :: AstronomicalUnits -> DecimalHours
lightTravelTime :: AstronomicalUnits -> DecimalHours
lightTravelTime (AU Double
ro) = Double -> DecimalHours
DH (Double -> DecimalHours) -> Double -> DecimalHours
forall a b. (a -> b) -> a -> b
$ Double
0.1386Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
ro


kmInOneAU :: Double
kmInOneAU :: Double
kmInOneAU = Double
149597870.700


-- | Convert from kilometers to Astronomical Units

kmToAU :: Double -> AstronomicalUnits
kmToAU :: Double -> AstronomicalUnits
kmToAU Double
km = Double -> AstronomicalUnits
AU (Double
km Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
kmInOneAU)


-- | Comvert from Astronomical Units to kilometers

auToKM :: AstronomicalUnits -> Double
auToKM :: AstronomicalUnits -> Double
auToKM (AU Double
au) = Double
au Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
kmInOneAU


-- | Convert from DecimalDegrees to Radians

toRadians :: DecimalDegrees -> Double
toRadians (DD Double
deg) = Double -> Double
forall a. Floating a => a -> a
U.toRadians Double
deg


-- | Convert from Radians to DecimalDegrees

fromRadians :: Double -> DecimalDegrees
fromRadians Double
rad = Double -> DecimalDegrees
DD (Double -> DecimalDegrees) -> Double -> DecimalDegrees
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
U.fromRadians Double
rad


-- | Convert Degrees, Minutes, Seconds to DecimalDegrees

fromDMS :: RealFrac a => Int -> Int -> a -> DecimalDegrees
fromDMS :: Int -> Int -> a -> DecimalDegrees
fromDMS Int
d Int
m a
s =
  let d' :: Double
d' = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
d
      m' :: Double
m' = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
m
      s' :: Double
s' = a -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac a
s
  in Double -> DecimalDegrees
DD (Double -> DecimalDegrees) -> Double -> DecimalDegrees
forall a b. (a -> b) -> a -> b
$ Double
d'Double -> Double -> Double
forall a. Num a => a -> a -> a
+(Double
m'Double -> Double -> Double
forall a. Num a => a -> a -> a
+(Double
s'Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
60))Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
60


-- | Convert DecimalDegrees to Degrees, Minutes, Seconds

toDMS :: DecimalDegrees -> (a, b, Double)
toDMS (DD Double
dd) =
  let (a
d, Double
rm) = Double -> (a, Double)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction Double
dd
      (b
m, Double
rs) = Double -> (b, Double)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction (Double -> (b, Double)) -> Double -> (b, Double)
forall a b. (a -> b) -> a -> b
$ Double
60 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
rm
      s :: Double
s = Double
60 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
rs
  in (a
d, b
m, Double
s)


-- | Comvert Hours, Minutes, Seconds to DecimalHours

fromHMS :: RealFrac a => Int -> Int -> a -> DecimalHours
fromHMS :: Int -> Int -> a -> DecimalHours
fromHMS Int
h Int
m a
s =
  let h' :: Double
h' = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
h
      m' :: Double
m' = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
m
      s' :: Double
s' = a -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac a
s
  in Double -> DecimalHours
DH (Double -> DecimalHours) -> Double -> DecimalHours
forall a b. (a -> b) -> a -> b
$ Double
h'Double -> Double -> Double
forall a. Num a => a -> a -> a
+(Double
m'Double -> Double -> Double
forall a. Num a => a -> a -> a
+(Double
s'Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
60))Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
60


-- | Convert DecimalDegrees to Degrees, Minutes, Seconds

toHMS :: DecimalHours -> (a, b, Double)
toHMS (DH Double
dh) =
  let (a
h, Double
rm) = Double -> (a, Double)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction Double
dh
      (b
m, Double
rs) = Double -> (b, Double)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction (Double -> (b, Double)) -> Double -> (b, Double)
forall a b. (a -> b) -> a -> b
$ Double
60 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
rm
      s :: Double
s = Double
60 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
rs
  in (a
h, b
m, Double
s)