在Haskell中生成一个随机数

时间:2010-11-28 17:43:44

标签: haskell random

我终于想出了如何生成随机数,但编译器仍然抱怨我的代码。

代码:

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不是很好,所以这需要一段时间。感谢。

3 个答案:

答案 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)

由于kinvgcdE没有任何monadic,因此它们都不应包含任何do s,<-return s。

同样,您不需要(也不能)使用<-来获取kinvgcdE的结果。任何算术运算符都是如此。只需使用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'功能......