Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Division in Haskell, still don't get it

I still don't understand the division in Haskell. My first intention was to define a funcion like this:

piApprox :: (Integral a, Fractional b) => a -> b
piApprox n = 4 * sum [ (-1)^k / (2*k + 1) | k <- [0..n] ]

It doesn't work. Then, using the signature:

piApprox :: (Fractional a) => Int -> a

but it raises again the "Could not deduce" error.

If I run this code in the interpreter to find out what signature is the best, the result is:

Prelude> let piApprox n = 4 * sum [ (-1)^k / (2*k + 1) | k <- [0..n] ]
Prelude> :t piApprox
piApprox :: (Fractional a, Integral a) => a -> a

which raises "The type variable `a0' is ambiguous" error.

Right now, the only way to make this calculation that I could think of is including the Ratio package and then converting to double by using fromRational.

import Data.Ratio
piApprox n = (fromRational) $ 4 * sum [ (-1)^k % (2*k + 1) | k <- [0..n] ]

It works, but I don't think that's the best approach.

I also thought that even the input and output types were right in the signature, the intermediate operation (-1)^k / (2*k + 1) -- where the division is placed -- might be the problem, so I also defined:

piApprox' :: (Fractional a) => Int -> a
piApprox' n = 4 * sum [ (fromIntegral) $ (-1)^k / (2*k + 1) | k <- [0..n] ]

with no luck. What am I missing here?

like image 301
pferor Avatar asked Jan 04 '14 16:01

pferor


2 Answers

This should work:

piApprox n = 4 * sum [ fromIntegral ((-1)^k) / fromIntegral (2*k + 1) | k <- [0..n] ]

The fromIntegral function has a type signature of :

(Integral a, Num b) => a -> b

So it basically converts your Integral type to Num type.

The type of (/) is:

Fractional a => a -> a -> a, so you have to supply Fractional data to it.

The fromIntegral function will exactly achieve this by converting it to a Num type which includes Fractional types.

like image 191
Sibi Avatar answered Sep 19 '22 16:09

Sibi


Your problem is that you're mixing incompatible number types. You said that n is some Integral (specifically, Integer in this case). k <- [0..n] means that k is the same Integral type. Then you use the / division, which is part of the Fractional class. Which means your result would have to be both Integral and Fractional, and I don't think such a type exists.

The solution would be to convert k to your result type before using it with fromIntegral k.

like image 41
Cubic Avatar answered Sep 22 '22 16:09

Cubic