Ich versuche, einen Zufallsgenerator in einer runST
Anweisung zu verwenden und den Generator nach Gebrauch zurückzugeben, so kann es an anderer Stelle verwendet werden.Rückkehr Zufallsgenerator aus runST
Wenn ich nur einen Vektor zurückgeben, kompiliert der Code, aber wenn der Generator auf die Return-Anweisung das Hinzufügen der Kompilierung fehlschlägt. Wenn ich die Fehlermeldung richtig verstehe, heißt es, dass die Funktion, die an die monadische Falte übergeben wird, den Vektor nicht im selben Zustand verändert, aber ich kann nicht herausfinden, warum sie dann kompiliert, wenn ich den Zufallsgenerator aus der return-Anweisung weglasse.
Dies kompiliert:
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
Aber dies nicht:
randVector' :: (RandomGen g) => Int -> g -> (VU.Vector Int, g)
randVector' n g = runST $ do
vector <- VU.unsafeThaw (VU.enumFromN 1 n) :: ST s (VUM.MVector s Int)
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, g')
Die return-Anweisung mit dem gefrorenen Vektor und dem Zufallsgenerator erzeugt den folgenden Fehler:
Couldn't match expected type
ST s (VU.Vector Int, g)
with actual type(m0 (VU.Vector Int), g)