問題があることです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
ジェネリック保つことができます状態のモナドベースのインターフェイスの生成ファシリティを使用することができます。