私はrunST
文の中でランダムジェネレータを使い、使用後にジェネレータを返すようにしていますので、別の場所で使用することができます。runSTからランダムジェネレータを返す
ベクトルだけを返した場合、コードはコンパイルされますが、ジェネレータをreturn文に追加するとコンパイルが失敗します。エラーメッセージが正しく理解されていれば、モナドフォールドに渡された関数は同じ状態のベクタを変更しないと言いますが、return文からランダムジェネレータを省略すると、それがなぜコンパイルされるのか分かりません。
import Control.Monad
import Control.Monad.ST
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import System.Random
randVector :: (RandomGen g) => Int -> g -> VU.Vector Int
randVector n g = runST $ do
vector <- VU.unsafeThaw (VU.enumFromN 1 n)
let step g i = do let (j,g') = randomR (1,n) g
VUM.swap vector i j
return g'
g' <- foldM step g [1..VUM.length vector-1]
VU.unsafeFreeze vector
をしかし、これはしていません::
これはコンパイル
Couldn't match expected type
ST s (VU.Vector Int, g)
with actual type(m0 (VU.Vector Int), g)