2010-11-28 200 views
3

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

代码:

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 <ķ< Q之间的随机整数的值。我对Haskell不太好,所以这段时间已经过去了。谢谢。

回答

1

由于没有什么单子约kinvgcdE,一方都不应包含任何do S,<- S或return秒。

同样,您不需要(也不能)使用<-来获得kinvgcdE的结果。任何算术运算符也是如此。只需使用let result = non-monadic operation,而不是result <- non-monadic operation

+0

谢谢。它帮助! – 2010-11-28 18:39:29

2

以下是一个修复,事情是do结构用于绑定一元值,而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) 

应当注意的是,符号现在是一个IO的功能,所以它不能在纯代码中使用。依赖于随机生成器,通过封装种子值并将它传递给一个状态monad,它仍然可能具有纯函数。这种方式在Real World Haskell中描述。

+0

当我做了Haskell时,这真是太棒了,我从来没有遇到过单子。谢谢。我想通了,它完美的作品。 – 2010-11-28 18:41:53

0

有时候,如果你真的不需要计算,最好少用monad。

sign [email protected](_,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) 

所以,你可以更方便地测试标志”功能,如果事情是奇怪...