RosettaCodeData/Task/Knuth-shuffle/Haskell/knuth-shuffle-4.hs
2019-09-12 10:33:56 -07:00

21 lines
741 B
Haskell

import Data.Array.ST
import Data.STRef
import Control.Monad
import Control.Monad.ST
import Control.Arrow
import System.Random
shuffle :: RandomGen g => [a] -> g -> ([a], g)
shuffle list g = runST $ do
r <- newSTRef g
let rand range = liftM (randomR range) (readSTRef r) >>=
runKleisli (second (Kleisli $ writeSTRef r) >>> arr fst)
a <- newAry (1, len) list
forM_ [len, len - 1 .. 2] $ \n -> do
k <- rand (1, n)
liftM2 (,) (readArray a k) (readArray a n) >>=
runKleisli (Kleisli (writeArray a n) *** Kleisli (writeArray a k))
liftM2 (,) (getElems a) (readSTRef r)
where len = length list
newAry :: (Int, Int) -> [a] -> ST s (STArray s Int a)
newAry = newListArray