tags:

views:

266

answers:

4

Hey,

Whenever I write a function using doubles and integers, I find this problem where I am constantly having to use 'fromIntegral' everywhere in my function. For example:

import Data.List

roundDouble
    :: Double
    -> Int 
    -> Double
roundDouble x acc = fromIntegral (round $ x * 10 ** fromIntegral acc) / 10 ** fromIntegral acc

Is there an easier way of writing this? (I know there may be easier ways of rounding a number and if there are please let me know! However I am mainly interested in how to avoid using so many 'fromIntegrals'.)

Thanks, Ash

+8  A: 

You can use ^ instead of **. ^ takes any Integral as it's second argument, so you don't need to call fromIntegral on the second operand. So your code becomes:

roundDouble x acc = fromIntegral (round $ x * 10 ^ acc) / 10 ^ acc

Which has only one fromIntegral. And that one you can't get rid off as round naturally returns an Integral and you can't perform non-integer division on an Integral.

sepp2k
+5  A: 

I have a similar problem with marshaling code, where fromIntegral is used to convert CInt to Int. I usually define fI = fromIntegral to make it easier. You may also need to give it an explicit type signature or use -XNoMonomorphismRestriction.

If you're doing a lot of math, you may want to look at the Numeric Prelude, which seems to have much more sensible relations between different numeric types.

John
I was expecting to see the answer to be defining fI so I am glad to see someone else write it. I will check out the Numeric Prelude, it looks very useful, thanks!
Ash
Defining fI isn't as slick as some other answers, but it has the broadest applicability compared to the other answers so far.
John
+11  A: 

Sometimes I find a helper function useful:

roundDouble x acc = (round $ x * 10 ^ acc) /. (10 ^ acc)
    where 
    x /. y = fromIntegral x / fromIntegral y

That helper function can also be written:

(/.) = (/) `on` fromIntegral

Where on is from Data.Function.

luqui
Wasn't aware of `on`, thanks for pointing it out!
J Cooper
And its variant: http://stackoverflow.com/questions/3453608/overuse-of-fromintegral-in-haskell/3458922#3458922
jetxee
The type of (/.) is (Integral a, Fractional b, Integral a1) => a -> a1 -> b whereas the type of (/) `on` fromIntegral is (Fractional b, Integral a) => a -> a -> b.If you need the more general type, on is not appropriate.
Peaker
+3  A: 

Another idea, similar to luqui's. Most of my problems with fromIntegral are related to necessity to divide Int by Double or Double by Int. So this (/.) allows to divide any two Real types, not necessarily the same, an not necessarily Integral types like in luqui's solution:

(/.) :: (Real a, Real b, Fractional c) => a -> b -> c
(/.) x y = fromRational $ (toRational x) / (toRational y)

Example:

ghci> let (a,b,c) = (2::Int, 3::Double, 5::Int)
ghci> (b/.a, c/.a, a/.c)
(1.5,2.5,0.4)

It works for any two Reals, but I suspect that rational division and conversion to/from Rational are not very effective.

Now your example becomes:

roundDouble :: Double -> Int -> Double
roundDouble x acc = (round $ x * 10 ^ acc) /. (10 ^ acc)
jetxee