module System.Random.Shuffle.FisherYates (
shuffle
) where
import Control.Monad
import Control.Monad.ST
import Data.STRef
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as VM
import System.Random.TF
import System.Random.TF.Instances
shuffle :: [x] -> IO [x]
shuffle list = do
initGen <- newTFGen
pure $ V.toList $ runST $ do
genVar <- newSTRef initGen
v <- V.thaw $ V.fromList list
let vLen = VM.length v
forM_ [vLen 1, vLen 2 .. 1] $ \n -> do
indexToSwap <- randSTFromZero genVar n
VM.unsafeSwap v indexToSwap n
V.unsafeFreeze v
randSTFromZero :: STRef s TFGen -> Int -> ST s Int
randSTFromZero genVar maxVal = do
g0 <- readSTRef genVar
let (x, g1) = randomR (0, maxVal) g0
writeSTRef genVar g1
pure x