我终于想出了如何生成随机数,但编译器仍然抱怨我的代码。
代码:
type Quot = Integer
sign (p,q,g) (x,pub) d =
do k <- randomRIO(1,q-1 :: Integer)
ki <- kinv k q
r <- g^k `mod` p
s <- (160 + x*r)*ki mod q
return (r,s)
kinv :: Integer -> Quot -> Integer
kinv k q =
do (d,t,s) <- gcdE(q,k)
return s
gcdE(a,0) = (a,1,0)
gcdE(a,b) = (d,t,s - q*t)
where r = a `mod` b
q = a `div` b
(d,s,t) = gcdE(b,r)
错误讯息:
crypt.hs:24:7:
Couldn't match expected type `Integer' against inferred type `m a'
In a stmt of a 'do' expression: ki <- kinv k q
In the expression:
do { k <- randomRIO (1, q - 1 :: Integer);
ki <- kinv k q;
r <- g ^ k `mod` p;
s <- (160 + x * r) * ki mod q;
.... }
In the definition of `sign':
sign (p, q, g) (x, pub) d
= do { k <- randomRIO (1, q - 1 :: Integer);
ki <- kinv k q;
r <- g ^ k `mod` p;
.... }
crypt.hs:37:10:
Couldn't match expected type `Integer'
against inferred type `(Quot, Quot, b)'
In a stmt of a 'do' expression: (d, t, s) <- gcdE (q, k)
In the expression:
do { (d, t, s) <- gcdE (q, k);
return s }
In the definition of `kinv':
kinv k q
= do { (d, t, s) <- gcdE (q, k);
return s }
我想要的是变量k取0到0之间的随机整数值。 k&lt; Q值。我对Haskell不是很好,所以这需要一段时间。感谢。
答案 0 :(得分:2)
以下是修复,问题是do构造用于绑定monadic值,randomRIO(1,q-1)的类型为IO a,IO是monad,但kniv kq是整数类型所以它不适合do构造中的其他IO monad函数。我恳请你阅读monad tutorial。
sign (p,q,g) (x,pub) d = do
k <- randomRIO(1,q-1)
let ki = kinv k q
let r = mod ( g^k) p
let s = mod ((160 + x*r)*ki) q
return (r,s)
kinv k q = s
where (_,_,s) = gcdE(q,k)
gcdE(a,0) = (a,1,0)
gcdE(a,b) = (d,t,s - q*t)
where r = a `mod` b
q = a `div` b
(d,s,t) = gcdE(b,r)
应该注意,sign现在是一个IO功能,因此不能在纯代码中使用。依赖于随机生成器,通过封装种子值并在状态monad中传递它,仍然可以具有纯函数。这种方式在Real World Haskell中描述。
答案 1 :(得分:1)
由于kinv
或gcdE
没有任何monadic,因此它们都不应包含任何do
s,<-
或return
s。
同样,您不需要(也不能)使用<-
来获取kinv
和gcdE
的结果。任何算术运算符都是如此。只需使用let result = non-monadic operation
,而不是result <- non-monadic operation
。
答案 2 :(得分:0)
如果您在计算中不需要它们,有时候谨慎使用monads是个好主意。
sign a@(_,q,_) (x,pub) d = sign' a x <$> randomRIO(1,q-1)
sign' (p,q,g) x k = (r,s)
where r = mod (g ^ k) p
s = mod ((160 + x * r) * kinv k q) q
kinv k q = let (_,_,s) = gcdE(q,k) in s
gcdE(a,0) = (a,1,0)
gcdE(a,b) = (d,t,s - q*t)
where r = a `mod` b
q = a `div` b
(d,s,t) = gcdE(b,r)
所以,如果有些奇怪的话,你甚至可以更轻松地测试 sign'功能......