2012-01-14 11 views
1

乱数のリストを生成したいところです。乱数の範囲は、指定されたリストの要素によって決まります。私は意味を成していた何かを持っていたと思ったが、私は理解していないエラーが発生します:(foldMで乱数のリストを生成

ここで私が持っているものです:?

useRNG nums min = do 
    generator <- get 
    let (val, generator') = randomR (min, 51) generator 
    put generator' 
    return $ val : nums 

foldM useRNG [] [0 .. 50] 

誰も私を助けることができる

答えて

4

問題があることですuseRNGは、推論型シグネチャから分かるように、数値のすべての種類(Randomの任意のインスタンス)を生成し、モナドのすべての種類の動作(その状態RandomGenのインスタンスである任意の状態モナド)することができる:

GHCi> :t useRNG 
useRNG 
    :: (MonadState s m, RandomGen s, Random a, Num a) => 
    [a] -> a -> m [a] 

...しかし、あなたが実際に欲しい具体的なタイプを指定していない場合は、それを使用します。

あなたは型シグネチャを明確にした場合:

test :: State StdGen [Int] 
test = foldM useRNG [] [0 .. 50] 

それが正常に動作します。

useRNG :: [Int] -> Int -> State StdGen [Int] 

を今、あなたは考えるかもしれない:あなたはまた、useRNGに型シグネチャを置くことによって、これを達成できuseRNGができないのはなぜtestあまりにも、これらすべての種類の正常に動作しますか?答えは、monomorphism restrictionです。これは、非常に秘密で、多くのハスケルユーザーがうまく好きではありません。

test :: (RandomGen g, Random a, Num a, Enum a, MonadState g m) => m [a] 

あなたはGHCiので正しい型シグネチャを見つけることができます:

あなたはどちらかは、あなたのファイルの先頭に

{-# LANGUAGE NoMonomorphismRestriction #-} 

を入れ、またはtest明示的な型シグネチャを与えることによってそれを避けることができます

GHCi> :t foldM useRNG [] [0 .. 50] 
foldM useRNG [] [0 .. 50] 
    :: (MonadState s m, RandomGen s, Random b, Num b, Enum b) => m [b] 

(私はGHCiでチェックする前に明示的なタイプシグネチャを書いていたので、私のものは少し違います)

しかし、この型シグネチャは少しtoo実用には多岐にわたります。実際に結果を使用するまで基本的にあいまいさを取り除いていますので、具体的にこのインスタンスで指定することをお勧めします。すべての標準の乱数をラップ

test :: (Random a, Num a, Enum a) => State StdGen [a] 

あなたはまた、MonadRandomを使用して検討する必要があります:あなたは、例えば、Stateモナドと発電機の種類を超える不要な多型せずに乱数の種を超えるtestジェネリック保つことができます状態のモナドベースのインターフェイスの生成ファシリティを使用することができます。