{-# LANGUAGE BlockArguments, LambdaCase #-}
{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}

module Data.Angle (Angle, pattern Radian, radian, pattern Degree, degree) where

import Control.Arrow (second)
import Text.Read (Lexeme(..), readPrec, step, parens, prec, lexP, (+++))

---------------------------------------------------------------------------

-- * DATA TYPE AND PATTERN
-- * INSTANCE DEFINITION

---------------------------------------------------------------------------
-- DATA TYPE AND PATTERN
---------------------------------------------------------------------------

data Angle f = Radian_ f | Degree_ f

-- ^ >>> Radian pi
-- Radian 3.141592653589793
-- >>> degree it
-- 180.0
--
-- >>> Degree 180
-- Degree 180.0
--
-- >>> Radian pi + Degree 180
-- Radian 6.283185307179586

{-# COMPLETE Radian #-}

pattern Radian :: Floating f => f -> Angle f
pattern $bRadian :: f -> Angle f
$mRadian :: forall r f. Floating f => Angle f -> (f -> r) -> (Void# -> r) -> r
Radian r <- (radian -> r) where Radian = f -> Angle f
forall f. f -> Angle f
Radian_

radian :: Floating f => Angle f -> f
radian :: Angle f -> f
radian = \case Radian_ f
r -> f
r; Degree_ f
d -> f
d f -> f -> f
forall a. Num a => a -> a -> a
* f
forall a. Floating a => a
pi f -> f -> f
forall a. Fractional a => a -> a -> a
/ f
180

{-# COMPLETE Degree #-}

pattern Degree :: Floating f => f -> Angle f
pattern $bDegree :: f -> Angle f
$mDegree :: forall r f. Floating f => Angle f -> (f -> r) -> (Void# -> r) -> r
Degree d <- (degree -> d) where Degree = f -> Angle f
forall f. f -> Angle f
Degree_

degree :: Floating f => Angle f -> f
degree :: Angle f -> f
degree = \case Radian_ f
r -> f
r f -> f -> f
forall a. Num a => a -> a -> a
* f
180 f -> f -> f
forall a. Fractional a => a -> a -> a
/ f
forall a. Floating a => a
pi; Degree_ f
d -> f
d

---------------------------------------------------------------------------
-- INSTANCE DEFINITION
---------------------------------------------------------------------------

instance Show f => Show (Angle f) where
	showsPrec :: Int -> Angle f -> ShowS
showsPrec Int
d = \case
		Radian_ f
x -> Bool -> ShowS -> ShowS
showParen (Int
d Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
10)
			(ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ (String
"Radian " String -> ShowS
forall a. [a] -> [a] -> [a]
++) ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> f -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
11 f
x
		Degree_ f
x -> Bool -> ShowS -> ShowS
showParen (Int
d Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
10)
			(ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ (String
"Degree " String -> ShowS
forall a. [a] -> [a] -> [a]
++) ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> f -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
11 f
x

instance (Read f, Floating f) => Read (Angle f) where
	readPrec :: ReadPrec (Angle f)
readPrec = ReadPrec (Angle f) -> ReadPrec (Angle f)
forall a. ReadPrec a -> ReadPrec a
parens (ReadPrec (Angle f) -> ReadPrec (Angle f))
-> ReadPrec (Angle f) -> ReadPrec (Angle f)
forall a b. (a -> b) -> a -> b
$
		Int -> ReadPrec (Angle f) -> ReadPrec (Angle f)
forall a. Int -> ReadPrec a -> ReadPrec a
prec Int
10 do Ident String
"Radian" <- ReadPrec Lexeme
lexP; f -> Angle f
forall f. f -> Angle f
Radian_ (f -> Angle f) -> ReadPrec f -> ReadPrec (Angle f)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadPrec f -> ReadPrec f
forall a. ReadPrec a -> ReadPrec a
step ReadPrec f
forall a. Read a => ReadPrec a
readPrec
		ReadPrec (Angle f) -> ReadPrec (Angle f) -> ReadPrec (Angle f)
forall a. ReadPrec a -> ReadPrec a -> ReadPrec a
+++
		Int -> ReadPrec (Angle f) -> ReadPrec (Angle f)
forall a. Int -> ReadPrec a -> ReadPrec a
prec Int
10 do Ident String
"Degree" <- ReadPrec Lexeme
lexP; f -> Angle f
forall f. f -> Angle f
Degree_ (f -> Angle f) -> ReadPrec f -> ReadPrec (Angle f)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadPrec f -> ReadPrec f
forall a. ReadPrec a -> ReadPrec a
step ReadPrec f
forall a. Read a => ReadPrec a
readPrec

instance (Eq f, Floating f) => Eq (Angle f) where
	Degree_ f
x == :: Angle f -> Angle f -> Bool
== Degree_ f
y = f
x f -> f -> Bool
forall a. Eq a => a -> a -> Bool
== f
y; Radian f
x == Radian f
y = f
x f -> f -> Bool
forall a. Eq a => a -> a -> Bool
== f
y

instance (Ord f, Floating f) => Ord (Angle f) where
	Degree_ f
x <= :: Angle f -> Angle f -> Bool
<= Degree_ f
y = f
x f -> f -> Bool
forall a. Ord a => a -> a -> Bool
<= f
y; Radian f
x <= Radian f
y = f
x f -> f -> Bool
forall a. Ord a => a -> a -> Bool
<= f
y

instance Floating f => Num (Angle f) where
	Degree_ f
x + :: Angle f -> Angle f -> Angle f
+ Degree_ f
y = f -> Angle f
forall f. f -> Angle f
Degree_ (f -> Angle f) -> f -> Angle f
forall a b. (a -> b) -> a -> b
$ f
x f -> f -> f
forall a. Num a => a -> a -> a
+ f
y
	Radian f
x + Radian f
y = f -> Angle f
forall f. f -> Angle f
Radian_ (f -> Angle f) -> f -> Angle f
forall a b. (a -> b) -> a -> b
$ f
x f -> f -> f
forall a. Num a => a -> a -> a
+ f
y
	Degree_ f
x * :: Angle f -> Angle f -> Angle f
* Degree_ f
y = f -> Angle f
forall f. f -> Angle f
Degree_ (f -> Angle f) -> f -> Angle f
forall a b. (a -> b) -> a -> b
$ f
x f -> f -> f
forall a. Num a => a -> a -> a
* f
y f -> f -> f
forall a. Num a => a -> a -> a
* f
forall a. Floating a => a
pi f -> f -> f
forall a. Fractional a => a -> a -> a
/ f
180
	Radian f
x * Radian f
y = f -> Angle f
forall f. f -> Angle f
Radian_ (f -> Angle f) -> f -> Angle f
forall a b. (a -> b) -> a -> b
$ f
x f -> f -> f
forall a. Num a => a -> a -> a
* f
y
	negate :: Angle f -> Angle f
negate = \case Radian_ f
x -> f -> Angle f
forall f. f -> Angle f
Radian_ (f -> Angle f) -> f -> Angle f
forall a b. (a -> b) -> a -> b
$ - f
x; Degree_ f
x -> f -> Angle f
forall f. f -> Angle f
Degree_ (f -> Angle f) -> f -> Angle f
forall a b. (a -> b) -> a -> b
$ - f
x
	abs :: Angle f -> Angle f
abs = \case Radian_ f
x -> f -> Angle f
forall f. f -> Angle f
Radian_ (f -> Angle f) -> f -> Angle f
forall a b. (a -> b) -> a -> b
$ f -> f
forall a. Num a => a -> a
abs f
x; Degree_ f
x -> f -> Angle f
forall f. f -> Angle f
Degree_ (f -> Angle f) -> f -> Angle f
forall a b. (a -> b) -> a -> b
$ f -> f
forall a. Num a => a -> a
abs f
x
	signum :: Angle f -> Angle f
signum = \case
		Radian_ f
x -> f -> Angle f
forall f. f -> Angle f
Radian_ (f -> Angle f) -> f -> Angle f
forall a b. (a -> b) -> a -> b
$ f -> f
forall a. Num a => a -> a
signum f
x; Degree_ f
x -> f -> Angle f
forall f. f -> Angle f
Radian_ (f -> Angle f) -> f -> Angle f
forall a b. (a -> b) -> a -> b
$ f -> f
forall a. Num a => a -> a
signum f
x
	fromInteger :: Integer -> Angle f
fromInteger = f -> Angle f
forall f. f -> Angle f
Radian_ (f -> Angle f) -> (Integer -> f) -> Integer -> Angle f
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> f
forall a. Num a => Integer -> a
fromInteger

instance Floating f => Fractional (Angle f) where
	recip :: Angle f -> Angle f
recip = \case
		Radian_ f
x -> f -> Angle f
forall f. f -> Angle f
Radian_ (f -> Angle f) -> f -> Angle f
forall a b. (a -> b) -> a -> b
$ f -> f
forall a. Fractional a => a -> a
recip f
x
		Degree_ f
x -> f -> Angle f
forall f. f -> Angle f
Degree_ (f -> Angle f) -> f -> Angle f
forall a b. (a -> b) -> a -> b
$ f -> f
forall a. Fractional a => a -> a
recip f
x f -> f -> f
forall a. Num a => a -> a -> a
* (f
180 f -> f -> f
forall a. Fractional a => a -> a -> a
/ f
forall a. Floating a => a
pi) f -> Int -> f
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
2 :: Int)
	fromRational :: Rational -> Angle f
fromRational = f -> Angle f
forall f. f -> Angle f
Radian_ (f -> Angle f) -> (Rational -> f) -> Rational -> Angle f
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> f
forall a. Fractional a => Rational -> a
fromRational

instance (Floating f, Real f) => Real (Angle f) where
	toRational :: Angle f -> Rational
toRational = f -> Rational
forall a. Real a => a -> Rational
toRational (f -> Rational) -> (Angle f -> f) -> Angle f -> Rational
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Angle f -> f
forall f. Floating f => Angle f -> f
radian

instance Floating f => Floating (Angle f) where
	pi :: Angle f
pi = f -> Angle f
forall f. f -> Angle f
Radian_ f
forall a. Floating a => a
pi
	exp :: Angle f -> Angle f
exp = (f -> f) -> Angle f -> Angle f
forall f. Floating f => (f -> f) -> Angle f -> Angle f
applyAngle f -> f
forall a. Floating a => a -> a
exp
	log :: Angle f -> Angle f
log = (f -> f) -> Angle f -> Angle f
forall f. Floating f => (f -> f) -> Angle f -> Angle f
applyAngle f -> f
forall a. Floating a => a -> a
log
	sin :: Angle f -> Angle f
sin = (f -> f) -> Angle f -> Angle f
forall f. Floating f => (f -> f) -> Angle f -> Angle f
applyAngle f -> f
forall a. Floating a => a -> a
sin
	cos :: Angle f -> Angle f
cos = (f -> f) -> Angle f -> Angle f
forall f. Floating f => (f -> f) -> Angle f -> Angle f
applyAngle f -> f
forall a. Floating a => a -> a
cos
	asin :: Angle f -> Angle f
asin = (f -> f) -> Angle f -> Angle f
forall f. Floating f => (f -> f) -> Angle f -> Angle f
applyAngle f -> f
forall a. Floating a => a -> a
asin
	acos :: Angle f -> Angle f
acos = (f -> f) -> Angle f -> Angle f
forall f. Floating f => (f -> f) -> Angle f -> Angle f
applyAngle f -> f
forall a. Floating a => a -> a
acos
	atan :: Angle f -> Angle f
atan = (f -> f) -> Angle f -> Angle f
forall f. Floating f => (f -> f) -> Angle f -> Angle f
applyAngle f -> f
forall a. Floating a => a -> a
atan
	sinh :: Angle f -> Angle f
sinh = (f -> f) -> Angle f -> Angle f
forall f. Floating f => (f -> f) -> Angle f -> Angle f
applyAngle f -> f
forall a. Floating a => a -> a
sinh
	cosh :: Angle f -> Angle f
cosh = (f -> f) -> Angle f -> Angle f
forall f. Floating f => (f -> f) -> Angle f -> Angle f
applyAngle f -> f
forall a. Floating a => a -> a
cosh
	asinh :: Angle f -> Angle f
asinh = (f -> f) -> Angle f -> Angle f
forall f. Floating f => (f -> f) -> Angle f -> Angle f
applyAngle f -> f
forall a. Floating a => a -> a
asinh
	acosh :: Angle f -> Angle f
acosh = (f -> f) -> Angle f -> Angle f
forall f. Floating f => (f -> f) -> Angle f -> Angle f
applyAngle f -> f
forall a. Floating a => a -> a
acosh
	atanh :: Angle f -> Angle f
atanh = (f -> f) -> Angle f -> Angle f
forall f. Floating f => (f -> f) -> Angle f -> Angle f
applyAngle f -> f
forall a. Floating a => a -> a
atanh

applyAngle :: Floating f => (f -> f) -> Angle f -> Angle f
applyAngle :: (f -> f) -> Angle f -> Angle f
applyAngle f -> f
f = \case
	Radian_ f
x -> f -> Angle f
forall f. f -> Angle f
Radian_ (f -> Angle f) -> f -> Angle f
forall a b. (a -> b) -> a -> b
$ f -> f
f f
x
	Degree_ f
x -> f -> Angle f
forall f. f -> Angle f
Degree_ (f -> Angle f) -> f -> Angle f
forall a b. (a -> b) -> a -> b
$ f -> f
f (f
x f -> f -> f
forall a. Num a => a -> a -> a
* f
forall a. Floating a => a
pi f -> f -> f
forall a. Fractional a => a -> a -> a
/ f
180) f -> f -> f
forall a. Num a => a -> a -> a
* f
180 f -> f -> f
forall a. Fractional a => a -> a -> a
/ f
forall a. Floating a => a
pi

instance (Floating f, RealFrac f) => RealFrac (Angle f) where
	properFraction :: Angle f -> (b, Angle f)
properFraction = \case
		Radian_ f
x -> f -> Angle f
forall f. Floating f => f -> Angle f
Radian (f -> Angle f) -> (b, f) -> (b, Angle f)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
`second` f -> (b, f)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction f
x
		Degree_ f
x -> (f -> Angle f
forall f. f -> Angle f
Degree_ (f -> Angle f) -> (f -> f) -> f -> Angle f
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (f -> f -> f
forall a. Fractional a => a -> a -> a
/ f
forall a. Floating a => a
pi) (f -> f) -> (f -> f) -> f -> f
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (f -> f -> f
forall a. Num a => a -> a -> a
* f
180))
			(f -> Angle f) -> (b, f) -> (b, Angle f)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
`second` f -> (b, f)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction (f
x f -> f -> f
forall a. Num a => a -> a -> a
* f
forall a. Floating a => a
pi f -> f -> f
forall a. Fractional a => a -> a -> a
/ f
180)