Hello everybody this is my first question here. I just going crazy because of this and not found any information about it...
This is an example of the original code to simulate the problem:
module Code where
import Data.List
list e = [e, e*2 .. 10000]
exp1 z e = (((elemIndices 0 (map (`mod` e) (map (+1) (list z))))!!0 +1)*z +1) `div` e
prub v1 v2 e l = map (`mod` (v1*v2)) (map (product) (map (replicate (exp1 ((v1-1)*(v2-1)) e)) l))
this code with the following variables (31 11 7 [235,302,210,123,255])
returns this list: [106,70,246,160,277]
. But this isn't what I looking for.
But if I change the (v1*v2)
for 341 which is the product of v1*v2
(11*31
in the example) the output is the following list [20,15,12,30,19]
. This it's what I want.
prub v1 v2 e l = map (`mod` 341) (map (product) (map (replicate (exp1 ((v1-1)*(v2-1)) e)) l))
So why exist different returns with the EXACT SAME values?
Sorry for my english. If you want to know what I want to make is a RSA encryption in haskell
Edit: forgive me for the mistakes in code, I edit the text and put a reproducible code.
The problem is a difference in the inferred type for prub
in the two versions. The "wrong" version uses Int
, which overflows, while the "right" version uses Integer
, which doesn't overflow.
In your original version (that uses v1*v2
), the function exp1
has inferred type Int -> Int -> Int
. This is because the elemIndices
call has return type [Int]
, which results in the types of the arguments and return value being similarly inferred as Int
. Because you have:
exp1 :: Int -> Int -> Int
the call to exp1
in prub
with its first argument ((v1-1)*(v2-1))
causes both v1
and v2
to be assigned type Int
. When you take a mod
by v1*v2
, this causes the type of l
to be inferred as [Int]
.
In contrast, when you replace v1*v2
with 341
, even though the types of v1
and v2
are still inferred as Int
, the type of 341
is inferred as an unspecified Integral
. The resulting type for prub
is:
prub :: Integral b => Int -> Int -> Int -> [b] -> [b]
When you call prub
in your test case using 341
in place of v1*v2
:
prub 31 11 7 [235,302,210,123,255]
the type of the final argument defaults to [Integer]
avoiding the overflow.
To fix it, you should provide a means to perform the necessary calculations on Integer
instead of Int
. I guess I'd recommend explicit type signatures and a fromIntegral
call to convert between Int
and Integer
where necessary:
list :: Int -> [Int]
list e = [e, e*2 .. 10000]
exp1 :: Int -> Int -> Int
exp1 z e = (((elemIndices 0 (map (`mod` e) (map (+1) (list z))))!!0 +1)*z +1) `div` e
prub :: Int -> Int -> Int -> [Integer] -> [Integer]
prub v1 v2 e l = map (`mod` fromIntegral (v1*v2)) (map (product) (map (replicate (exp1 ((v1-1)*(v2-1)) e)) l))