Given two ranges:

   



[

a

1


,

a

2


]


{\displaystyle [a_{1},a_{2}]}

   and 
   



[

b

1


,

b

2


]


{\displaystyle [b_{1},b_{2}]}

; 
   then a value   



s


{\displaystyle s}

   in range   



[

a

1


,

a

2


]


{\displaystyle [a_{1},a_{2}]}


   is linearly mapped to a value   



t


{\displaystyle t}

   in range   



[

b

1


,

b

2


]


{\displaystyle [b_{1},b_{2}]}


   where:



   



t
=

b

1


+



(
s
−

a

1


)
(

b

2


−

b

1


)


(

a

2


−

a

1


)





{\displaystyle t=b_{1}+{(s-a_{1})(b_{2}-b_{1}) \over (a_{2}-a_{1})}}




Task

Write a function/subroutine/... that takes two ranges and a real number, and returns the mapping of the real number from the first to the second range.

Use this function to map values from the range    [0, 10]    to the range    [-1, 0]. 



Extra credit

Show additional idiomatic ways of performing the mapping, using tools available to the language.




import Data.Ratio
import Text.Printf (PrintfType, printf)
 
-- Map a value from the range [a1,a2] to the range [b1,b2].  We don't check
-- for empty ranges.
mapRange
  :: Fractional a
  => (a, a) -> (a, a) -> a -> a
mapRange (a1, a2) (b1, b2) s = b1 + (s - a1) * (b2 - b1) / (a2 - a1)
 
main :: IO ()
main
-- Perform the mapping over floating point numbers.
 = do
  putStrLn "---------- Floating point ----------"
  mapM_ (\n -> prtD n . mapRange (0, 10) (-1, 0) $ fromIntegral n) [0 .. 10]
  -- Perform the same mapping over exact rationals.
  putStrLn "---------- Rationals ----------"
  mapM_ (\n -> prtR n . mapRange (0, 10) (-1, 0) $ n % 1) [0 .. 10]
  where
    prtD
      :: PrintfType r
      => Integer -> Double -> r
    prtD = printf "%2d -> %6.3f\n"
    prtR
      :: PrintfType r
      => Integer -> Rational -> r
    prtR n x = printf "%2d -> %s\n" n (show x)