2010-11-28 13 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 } 

私が欲しいのは、0 < K < Qの間のランダムな整数値を取る変数kのためです。私はハスケルにはあま​​りよくないので、これはしばらく時間がかかりました。ありがとう。

答えて

1

kinvまたはgcdEについてモナド何もないので、それらのいずれも任意のdo秒、<-秒またはreturn秒を含める必要があります。

同様に、<-を使用してkinvgcdEの結果を得る必要はありません。算術演算子についても同様です。 ではなく、let result = non-monadic operationを使用してください。

+0

ありがとうございました。それは助けになった! –

2

以下は修正されていますが、do構造体はモナド値をバインドするために使用され、randomRIO(1、q-1)はIO a型でIOはモナドですが、kniv kqは型それはdo構造の他のIOモナド関数には適合しません。 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関数なので、純粋なコードでは使用できません。シードされた値をカプセル化し、それを状態モナドに沿って渡すことによって、ランダムなジェネレータに依存する純粋な関数を持つことは、依然として可能です。この方法はReal World Haskellに記載されています。

+0

私がハスケルをしていたのはすばらしかったし、モナドもなかった。ありがとう。私はそれを理解し、それは完全に動作します。 –

0

実際に計算に必要ない場合は、モナドを控えめに使用することをお勧めします。何かが奇妙であれば

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) 

だから、あなたも、より簡単に記号」機能をテストすることができます...