当我重复它们时,haskell 中的变量会毫无逻辑地改变

Tom*_*zzo 4 encryption math haskell functional-programming rsa

大家好,这是我的第一个问题。我只是因为这个而发疯,没有找到任何有关它的信息......

这是模拟该问题的原始代码示例:

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))
Run Code Online (Sandbox Code Playgroud)

具有以下变量的代码(31 11 7 [235,302,210,123,255])返回此列表:[106,70,246,160,277]。但这不是我要找的。

但是,如果我更改(v1*v2)341 的乘积v1*v211*31在示例中),则输出为以下列表[20,15,12,30,19]。这就是我想要的。

prub v1 v2 e l = map (`mod` 341) (map (product) (map (replicate (exp1 ((v1-1)*(v2-1)) e)) l))
Run Code Online (Sandbox Code Playgroud)

那么为什么存在具有完全相同值的不同回报呢?

对不起我的英语不好。如果你想知道我想要做的是 haskell 中的 RSA 加密

编辑:请原谅我代码中的错误,我编辑文本并添加可重现的代码。

K. *_*uhr 9

prub问题在于两个版本中推断类型的差异。“错误”版本使用Int,它会溢出,而“正确”版本使用Integer,它不会溢出。

在您的原始版本(使用v1*v2)中,该函数exp1具有推断类型Int -> Int -> Int。这是因为elemIndices调用具有返回类型[Int],这会导致参数和返回值的类型被类似地推断为Int。因为你有:

exp1 :: Int -> Int -> Int
Run Code Online (Sandbox Code Playgroud)

使用第一个参数调用exp1in会导致和都被分配为 type 。当您采用by时,这会导致 的类型被推断为。prub((v1-1)*(v2-1))v1v2Intmodv1*v2l[Int]

相反,当您替换v1*v2为时,即使 和的341类型仍被推断为, 的类型也会被推断为未指定的。的结果类型是:v1v2Int341Integralprub

prub :: Integral b => Int -> Int -> Int -> [b] -> [b]
Run Code Online (Sandbox Code Playgroud)

当您调用prub测试用例时,使用341代替v1*v2

prub 31 11 7 [235,302,210,123,255]
Run Code Online (Sandbox Code Playgroud)

最后一个参数的类型默认是为了[Integer]避免溢出。

要解决此问题,您应该提供一种方法来执行必要的计算,Integer而不是Int. 我想我会推荐显式类型签名以及在必要时fromIntegral进行转换的调用:IntInteger

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))
Run Code Online (Sandbox Code Playgroud)