RosettaCodeData/Task/Angles-geometric-normalization-and-conversion/Haskell/angles-geometric-normalization-and-conversion-1.hs
2023-07-01 13:44:08 -04:00

35 lines
1,000 B
Haskell

{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import Text.Printf
class (Num a, Fractional a, RealFrac a) => Angle a where
fullTurn :: a -- value of the whole turn
mkAngle :: Double -> a
value :: a -> Double
fromTurn :: Double -> a
toTurn :: a -> Double
normalize :: a -> a
-- conversion of angles to rotations in linear case
fromTurn t = angle t * fullTurn
toTurn a = value $ a / fullTurn
-- normalizer for linear angular unit
normalize a = a `modulo` fullTurn
where
modulo x r | x == r = r
| x < 0 = signum x * abs x `modulo` r
| x >= 0 = x - fromInteger (floor (x / r)) * r
-- smart constructor
angle :: Angle a => Double -> a
angle = normalize . mkAngle
-- Two transformers differ only in the order of type application.
from :: forall a b. (Angle a, Angle b) => a -> b
from = fromTurn . toTurn
to :: forall b a. (Angle a, Angle b) => a -> b
to = fromTurn . toTurn