This small program works well with concrete types of Int
but I wanted to try to make the function the most general with type constraints.
The problem is that I don't understand the error message as the two "rigid types" seem to have the same constraints, but can't be matched.
module PotentiationNew where
import Data.Bits (FiniteBits, testBit, finiteBitSize, countLeadingZeros)
potentiation :: (Num a, Integral a, FiniteBits b) => a -> b -> a -> a
potentiation base exponent modulus =
potentiationGo $ getBits exponent
where
potentiationGo :: (Num c, Integral c) => [Bool] -> c
potentiationGo [] = 1
potentiationGo (currentExp : restExp)
| currentExp = (x * x * base) `mod` modulus -- This is the line with the error
| otherwise = (x * x) `mod` modulus
where x = potentiationGo restExp
-- Gets a bit array represented as [Bool] (True is 1)
-- Bit order starts with the least significant bits.
getBits :: FiniteBits a => a -> [Bool]
getBits x = testBit x <$> indexed
where
indexed = [0 .. finiteBitSize x - countLeadingZeros x - 1]
Here is the error message:
Potentiation.hs:13:22: error:
• Couldn't match expected type ‘c’ with actual type ‘a’
‘a’ is a rigid type variable bound by
the type signature for:
potentiation :: forall a b.
(Num a, Integral a, FiniteBits b) =>
a -> b -> a -> a
at Potentiation.hs:6:17
‘c’ is a rigid type variable bound by
the type signature for:
potentiationGo :: forall c. (Num c, Integral c) => [Bool] -> c
at Potentiation.hs:10:23