Reputation: 49
modPow :: Int -> Int -> Int -> Int
-- Pre: 1 <= m <= sqrt(maxint)
modPow x y n
|even y = (((x^halfy) `mod` n)^2) `mod` n
|otherwise = (x `mod` n)*(x ^ (y-1) `mod` n) `mod` n
where halfy = round (y/2)
REPORT ON TERMINAL:
Recursion.hs:39:19:
No instance for (RealFrac Int) arising from a use of ‘round’
In the expression: round (y / 2)
In an equation for ‘halfy’: halfy = round (y / 2)
In an equation for ‘modPow’:
modPow x y n
| even y = (((x ^ halfy) `mod` n) ^ 2) `mod` n
| otherwise = (x `mod` n) * (x ^ (y - 1) `mod` n) `mod` n
where
halfy = round (y / 2)
Recursion.hs:39:27:
No instance for (Fractional Int) arising from a use of ‘/’
In the first argument of ‘round’, namely ‘(y / 2)’
In the expression: round (y / 2)
In an equation for ‘halfy’: halfy = round (y / 2)
Upvotes: 1
Views: 1262
Reputation: 27636
In halfy = round (y/2)
, you have y :: Int
. However, the (/)
operator is defined in the Fractional
typeclass (which Int
is not an instance of; think about which Int
could represent e.g. 3/2
).
However, there are also the integer division operators div
and quot
which will give you rounded, Int
results. So just replace that definition of halfy
with
halfy = y `quot` 2
This will recover your inteded behaviour of halfy
since, forgetting about the typing issues for a moment, the fractional part of y/2
is always going to be either 0 or 0.5, and round
rounds both towards 0:
Prelude> round (1/2) :: Int
0
Prelude> round (-1/2) :: Int
0
Prelude> 1 `quot` 2 :: Int
0
Prelude> (-1) `quot` 2 :: Int
0
Prelude> (-1) `div` 2 :: Int -- This doesn't recover the same behaviour for negative y!
-1
Upvotes: 3