```
module Data.Angle where

import Data.Fixed -- mod'

newtype Angle a = Radians { angleValueRadians :: a } deriving (Eq, Show)

-- Creating Angle from a value

-- | Create an Angle with the given degrees
angleFromDegrees :: (Integral d, Floating r) => d -> Angle r
angleFromDegrees x = Radians \$ (realToFrac x) * pi/180

-- | Create an Angle with the given turns
angleFromTurns :: (Real t, Floating r) => t -> Angle r
angleFromTurns x = Radians \$ (realToFrac x) * pi*2

-- | Create an Angle with the given turns
angleFromRadians :: (Floating r) => r -> Angle r

-- Get the value from angle

-- | Get degrees from an angle
angleValueDegrees :: (Floating r, RealFrac r, Integral d) => Angle r -> d
angleValueDegrees (Radians x) = round \$ x / pi * 180.0

-- | Get turns from an angle
angleValueTurns :: (Floating r) => Angle r -> r
angleValueTurns (Radians x) = x / (pi*2)

-- Functor and Applicative instance

instance Functor Angle where
fmap f (Radians x) = Radians (f x)

instance Applicative Angle where
Radians f <*> r = fmap f r

-- Basic functions

-- | Adding two angles
addAngle :: (Floating a) => Angle a -> Angle a -> Angle a
addAngle r1 r2 = (+) <\$> r1 <*> r2

-- | Normalize Angle: transforming back to (0-2pi)
normAngle :: (Floating a, Real a) => Angle a -> Angle a
normAngle (Radians r) = Radians \$ mod' r (pi*2)

-- | Add two angles and normalize the result
addAngleNorm :: (Floating a, Real a) => Angle a -> Angle a -> Angle a
addAngleNorm a b = normAngle \$ addAngle a b

-- | Distance between two angles
distAngle :: (Floating a, Real a) => Angle a -> Angle a -> Angle a
distAngle (Radians r1) (Radians r2) = Radians \$ if (a' < b') then a' else b'
where
a' = mod' (r1-r2) (pi*2)
b' = mod' (r2-r1) (pi*2)

-- | Flip angle
flipAngle :: (Floating a) => Angle a -> Angle a
flipAngle = fmap negate

-- | Flip angle and normalize the result
flipAngleNorm :: (Floating a, Real a) => Angle a -> Angle a
flipAngleNorm = normAngle . flipAngle

-- | Add degrees to angle
addAngleDegrees :: (Floating r, Integral d) => Angle r -> d -> Angle r
addAngleDegrees ang deg = addAngle ang \$ angleFromDegrees deg

addAngleRadians :: (Floating r) => Angle r -> r -> Angle r

-- | Add turns to angle
addAngleTurns :: (Floating r, Real t) => Angle r -> t -> Angle r
addAngleTurns ang turn = addAngle ang \$ angleFromTurns turn

-- Trigonometric functions

-- | Sine of the angle
sinAngle :: (Floating a) => Angle a -> a
sinAngle = sin . angleValueRadians

-- | Cosine of the angle
cosAngle :: (Floating a) => Angle a -> a
cosAngle = cos . angleValueRadians

-- | Tangent of the angle
tanAngle :: (Floating a) => Angle a -> a
tanAngle = tan . angleValueRadians

-- | Cotangent of the angle
cotAngle :: (Floating a) => Angle a -> a
cotAngle = recip . tan . angleValueRadians

-- Inverse trigonometric functions

-- | Create angle from inverse sine
asinAngle :: (Floating a) => a -> Angle a
asinAngle = Radians . asin

-- | Create angle from inverse cosine
acosAngle :: (Floating a) => a -> Angle a
acosAngle = Radians . acos

-- | Create angle from inverse tangent
atanAngle :: (Floating a) => a -> Angle a
atanAngle = Radians . atan

-- | Create angle from inverse cotangent
acotAngle :: (Floating a) => a -> Angle a
acotAngle x = Radians \$ (pi/2) - (atan x)

-- | Create angle from atan2
atan2Angle :: (Floating a, RealFloat a) => a -> a -> Angle a
atan2Angle y x = Radians \$ atan2 y x

```