Related
The list monad provides an excellent abstraction for backtracking in
search problems. However, the problem I am facing now is one which
involves state in addition to backtracking. (It also involves
constraints related to previous choices made in the search path, but I
will attack that issue later.)
The following simplified example illustrates the problematics. The
function sumTo is given a nonnegative integer and a list with pairs
of integers. The first element in each pair is a positive integer, the
second element is the number of such integers available. The search
problem is to express the first argument using the integers in the
list, with count constraints. For example, here the integer 8 is
represented in different ways as sums of five 1s, three 2s and two
4s with the contraint that all numbers making up the sum have to be
even (so the 1s can not be used).
λ> sumTo 8 [(1,5), (4,2), (2,3)]
[[4,4],[4,2,2],[2,2,4],[2,4,2]]
The following is my current recursive solution to the problem.
sumTo :: Int -> [(Int, Int)] -> [[Int]]
sumTo = go []
where
go :: [(Int, Int)] -> Int -> [(Int, Int)] -> [[Int]]
go _ 0 _ = [[]] -- base case: success
go _ _ [] = [] -- base case: out of options, failure
-- recursion step: use the first option if it has counts left and
-- is suitable; append to this cases where current option is not
-- used at this point
go prevOpts n (opt#(val,cnt):opts) =
(if cnt > 0 && val <= n && even val
then map (val:) $ go [] (n - val) $ (val,cnt-1):(prevOpts ++ opts)
else [])
++ go (opt:prevOpts) n opts
While the function seems to work ok, it is much more complicated
than one without state, employing the list monad.
sumToN :: Int -> [Int] -> [[Int]]
sumToN 0 _ = [[]]
sumToN n opts = do
val <- opts
guard $ val <= n
guard $ even val
map (val:) $ sumToN (n - val) opts
Not having constraints, this one gives one additional solution.
λ> sumToN 8 [1, 4, 2]
[[4,4],[4,2,2],[2,4,2],[2,2,4],[2,2,2,2]]
Now I am wondering if some higher order abstraction, such as
StateT or something similar, could be utilized to simplify the case
of backtracking with this kind of state constraints.
There are two versions below, the first that just uses lists, and the second with StateT.
import Control.Applicative
import Control.Monad.State
The list type is the type of nondeterministic computations.
Given a set of elements (given in compact form as a list of (element, nb_copies)), we can pick any one, and return it together with the updated set. The result is a pair (Int, [(Int, Int)]). As a regular function, pick returns all possible results of that action.
Internally, we can also follow the definition with an "imperative" point of view. If the list is empty, there is nothing to pick (the empty list is the failing computation). Otherwise, there is at least one element x (implicitly, i > 0). Then we either pick one x (pickx), or we pick one element from the rest (pickxs), being careful to put x back at the end.
pick :: [(Int, Int)] -> [(Int, [(Int, Int)])]
pick [] = []
pick ((x, i) : xs) = pickx ++ pickxs
where
pickx = if i == 1 then [ (x, xs) ] else [ (x, (x, i-1) : xs) ]
pickxs = do
(x', xs') <- pick xs
return (x', (x, i) : xs')
Then sumTo is defined as follows: if n = 0 then the only solution is the empty sum ([]) and we return it. Otherwise, we pick one element i from the set, check its validity, and recursively look for a solution for n-i with the updated set.
sumTo :: Int -> [(Int, Int)] -> [[Int]]
sumTo = go
where
go 0 _ = return []
go n xs = do
(i, xs') <- pick xs
guard $ i <= n
guard $ even i
s' <- go (n-i) xs'
return (i : s')
Now threading the set around can be tedious. StateT transforms a type of computation to be stateful. [] is nondeterministic computation. StateT s [] is stateful nondeterministic computation, with state type s. Here the state will be the set of remaining elements.
Interestingly, pick can directly be interpreted as such a stateful computation. The intuition is that executing pickState removes an element from the state, which updates the state, and returns that element. pickState automatically fails if there are no more elements.
pickState :: StateT [(Int, Int)] [] Int
pickState = StateT pick
Then we repeatedly pick elements until we reach 0.
sumToState :: Int -> StateT [(Int, Int)] [] [Int]
sumToState = go
where
go 0 = return []
go n = do
i <- pickState
guard $ i <= n
guard $ even i
s' <- go (n-i)
return (i : s')
main = do
let n = 8
xs = [(1, 5), (4, 2), (2, 3)]
print $ sumTo n xs
print $ evalStateT (sumToState n) xs
(full source)
It's not much work to add the StateT monad transformer to your clean solution. You just need to add a layer of wrapping and unwrapping to lift the values into the StateT type, and then take them back out using evalStateT.
Your code would also benefit from internally using a more specialized type for the opts than [(Int, Int)]. MultiSet would be a good choice since it automatically manages occurrences.
Here's a tested example of what it could look like:
import Control.Monad.State (StateT, evalStateT, get, modify, lift, guard)
import Data.MultiSet (MultiSet, fromOccurList, distinctElems, delete)
sumToN :: Int -> [(Int, Int)] -> [[Int]]
sumToN nStart optsStart =
evalStateT (go nStart) (fromOccurList optsStart)
where
go :: Int -> StateT (MultiSet Int) [] [Int]
go 0 = return []
go n = do
val <- lift . distinctElems =<< get
guard (val <= n && even val)
modify (delete val)
(val:) <$> go (n - val)
λ> sumToN 8 [(1,5), (4,2), (2,3)]
[[2,2,4],[2,4,2],[4,2,2],[4,4]]
And actually, the StateT isn't benefiting us very much here. You could refactor it to take the MultiSet Int as a parameter and it would work just as well.
import Control.Monad (guard)
import Data.MultiSet (fromOccurList, distinctElems, delete)
sumToN :: Int -> [(Int, Int)] -> [[Int]]
sumToN nStart optsStart =
go nStart (fromOccurList optsStart)
where
go 0 _ = return []
go n opts = do
val <- distinctElems opts
guard (val <= n && even val)
(val:) <$> go (n - val) (delete val opts)
Simulating a lottery of 6 numbers chosen from 40, I want to create a list of numbers in Haskell using the system random generator but eliminate duplicates, which often arise.
If I have the following:
import System.Random
main :: IO ()
main = do
rs <- forM [1..6] $ \_x -> randomRIO (1, 40) :: (IO Int)
print rs
this is halfway. But how do I filter out duplicates? It seems to me I need a while loop of some sort to construct a list filtering elements that are already in the list until the list is the required size. If I can generate an infinite list of random numbers and filter it inside the IO monad I am sure that would work, but I do not know how to approach this. It seems while loops are generally deprecated in Haskell, so I am uncertain of the true Haskeller's way here. Is this a legitimate use case for a while loop, and if so, how does one do that?
The function you are looking for is nub from Data.List, to filter dublicates.
import Data.List
import System.Random
main = do
g <- newStdGen
print . take 6 . nub $ (randomRs (1,40) g :: [Int])
If you don't mind using a library, then install the random-shuffle package and use it like this:
import System.Random.Shuffle
import Control.Monad.Random
main1 = do
perm <- evalRandIO $ shuffleM [1..10]
print perm
If you want to see how to implement a naive Fischer-Yates shuffle using lists in Haskell, have a look at this code:
shuffle2 xs g = go [] g (length xs) xs
where
go perm g n avail
| n == 0 = (perm,g)
| otherwise = let (i, g') = randomR (0,n-1) g
a = avail !! i
-- can also use splitAt to define avail':
avail' = take i avail ++ drop (i+1) avail
in go (a:perm) g' (n-1) avail'
main = do
perm <- evalRandIO $ liftRand $ shuffle2 [1..10]
print perm
The parameters to the go helper function are:
perm - the constructed permutation so far
g - the current generator value
n - the length of the available items
avail - the available items - i.e. items not yet selected to be part of the permutation
go simply adds a random element from avail to the permutation being constructed and recursively calls itself with the new avail list and new generator.
To only draw k random elements from xs, just start go at k instead of length xs:
shuffle2 xs k g = go [] g k xs
...
You could also use a temporary array (in the ST or IO monad) to implement a Fischer-Yates type algorithm. The shuffleM function in random-shuffle uses a yet completely different approach which you might find interesting.
Update: Here is an example of using an ST-array in a F-Y style algorithm:
import Control.Monad.Random
import Data.Array.ST
import Control.Monad
import Control.Monad.ST (runST, ST)
shuffle3 :: RandomGen g => Int -> g -> ([Int], g)
shuffle3 n g0 = runST $ do
arr <- newListArray (1,n) [1..n] :: ST s (STUArray s Int Int)
let step g i = do let (j,g') = randomR (1,n) g
-- swap i and j
a <- readArray arr i
b <- readArray arr j
writeArray arr j a
writeArray arr i b
return g'
g' <- foldM step g0 [1..n]
perm <- getElems arr
return (perm, g')
main = do
perm <- evalRandIO $ liftRand $ shuffle3 20
print perm
I've used the Fisher Yates Shuffle in C++ with a decent random number generator to great success. This approach is very efficient if you are willing to allocate an array for holding numbers 1 to 40.
Going the strict IO way requires to break down nub, bringing the condition into the tail recursion.
import System.Random
randsf :: (Eq a, Num a, Random a) => [a] -> IO [a]
randsf rs
| length rs > 6 = return rs
| otherwise = do
r <- randomRIO (1,40)
if elem r rs
then randsf rs
else randsf (r:rs)
main = do
rs <- randsf [] :: IO [Int]
print rs
If you know what you do unsafeInterleaveIO from System.IO.Unsafe can be handy, allowing you to generate lazy lists from IO. Functions like getContents work this way.
import Control.Monad
import System.Random
import System.IO.Unsafe
import Data.List
rands :: (Eq a, Num a, Random a) => IO [a]
rands = do
r <- randomRIO (1,40)
unsafeInterleaveIO $ liftM (r:) rands
main = do
rs <- rands :: IO [Int]
print . take 6 $ nub rs
You commented:
The goal is to learn how to build a list monadically using filtering. It's a raw newbie question
Maybe you should change the question title then! Anyways, this is quite a common task. I usually define a combinator with a general monadic type that does what I want, give it a descriptive name (which I didn't quite succeed in here :-) and then use it, like below
import Control.Monad
import System.Random
-- | 'myUntil': accumulate a list with unique action results until the list
-- satisfies a test
myUntil :: (Monad m, Eq a) => ([a] -> Bool) -> m a -> m [a]
myUntil test action = myUntil' test [] action where
myUntil' test resultSoFar action = do
if test resultSoFar then
return resultSoFar
else do
x <- action
let newResults = if x `elem` resultSoFar then resultSoFar
else resultSoFar ++ [x] -- x:resultSoFar
myUntil' test newResults action
main :: IO ()
main = do
let enough xs = length xs == 6
drawNumber = randomRIO (0, 40::Int)
numbers <- myUntil enough drawNumber
print numbers
NB: this is not the optimal way to get your 6 distinct numbers, but meant as an example how to, in general, build a list monadically using a filter that works on the entire list
It is in essence the same as Vektorweg's longest answer, but uses a combinator with a much more general type (which is the way I like to do it, which may be more useful for you, given your comment at the top of this answer)
Recently I am trying to figure out how to do some programming in Haskell.
I'm trying to do some simple operations. Right now I'm stuck with an operation like in this example:
input = [1,2,3,4]
output = [1,2,2,3,3,3,4,4,4,4]
That is, for each element x in input, produce x elements of x in output. So, for element 1 in input, append [1] to output. Then, for element 2 in input, append elements [2,2] to output. Then, for element 3, append [3,3,3], etc. The algorithm should work only on standard numbers.
I know it's very easy, and it's trivial to perform it in "normal" imperative programming, but as Haskell's functions are stateless, I'm having a problem in how to approach this.
Could anyone please give me some hint how can an absolute Haskell beginner cope with this?
You've just discovered monads!
Here's the general idea of what you're doing:
For each a-element in the input (which is a container-type M a, here [a]), you specify an entire new container M b. But as a final result, you want just a single "flat" container M b.
Well, let's take a look at the definition of the Monad type class:
class (Applicative m) => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
which is exactly what you need. And lists are an instance of Monad, so you can write
replicates :: [Int] -> [Int]
replicates l = l >>= \n -> replicate n n
Alternatively, this can be written
replicates l = do
n <- l
replicate n n
It might be interesting to know that the, perhaps easier to understand, list comprehension
replicates l = [ n | n <- l, _ <- [1..n] ]
as suggested by chi, is actually just syntactic sugar for another monad expression:
[ n | n <- l, _ <- [1..n] ] ≡ l >>= \n -> [1..n] >>= \_ -> return n
... or least it used to be in some old version of GHC, I think it now uses a more optimised implementation of list comprehensions. You can still turn on that de-sugaring variant with the -XMonadComprehensions flag.
Yet another solution, exploiting list comprehensions:
output = [ n | n <- input , m <- [1..n] ]
Compare the above with the imperative Python code:
for n in input: -- n <- input
for m in range(1,n+1): -- m <- [1..n] (in Python the second extreme is excluded, hence +1)
print n -- the n in [ n | ... ]
Note that m is unused -- in Haskell it is customary to can call it _ to express this:
output = [ n | n <- input , _ <- [1..n] ]
As a beginner, I more easily understand something like this:
concat $ map (\x -> take x $ repeat x) [1,2,3,4]
For "list as monads" it is important to know that there is also "concat" operation under the hood (in bind definition), IMO
A simple solution:
rep (x:xs) = replicate x x ++ rep xs
rep [] = []
Hints:
replicate 5 "a" gives ["a","a","a","a","a"], and it works the same way for any type in the second argument, but first argument must be of type Int
the operator ++ concatenates two lists
so the inferred type of rep is [Int] -> [Int], if you need to use other types you should use conversion functions
I'm totally new to Haskell so apologies if the question is silly.
What I want to do is recursively build a list while at the same time building up an accumulated value based on the recursive calls. This is for a problem I'm doing for a Coursera course, so I won't post the exact problem but something analogous.
Say for example I wanted to take a list of ints and double each one (ignoring for the purpose of the example that I could just use map), but I also wanted to count up how many times the number '5' appears in the list.
So to do the doubling I could do this:
foo [] = []
foo (x:xs) = x * 2 : foo xs
So far so easy. But how can I also maintain a count of how many times x is a five? The best solution I've got is to use an explicit accumulator like this, which I don't like as it reverses the list, so you need to do a reverse at the end:
foo total acc [] = (total, reverse acc)
foo total acc (x:xs) = foo (if x == 5 then total + 1 else total) (x*2 : acc) xs
But I feel like this should be able to be handled nicer by the State monad, which I haven't used before, but when I try to construct a function that will fit the pattern I've seen I get stuck because of the recursive call to foo. Is there a nicer way to do this?
EDIT: I need this to work for very long lists, so any recursive calls need to be tail-recursive too. (The example I have here manages to be tail-recursive thanks to Haskell's 'tail recursion modulo cons').
Using State monad it can be something like:
foo :: [Int] -> State Int [Int]
foo [] = return []
foo (x:xs) = do
i <- get
put $ if x==5 then (i+1) else i
r <- foo xs
return $ (x*2):r
main = do
let (lst,count) = runState (foo [1,2,5,6,5,5]) 0 in
putStr $ show count
This is a simple fold
foo :: [Integer] -> ([Integer], Int)
foo [] = ([], 0)
foo (x : xs) = let (rs, n) = foo xs
in (2 * x : rs, if x == 5 then n + 1 else n)
or expressed using foldr
foo' :: [Integer] -> ([Integer], Int)
foo' = foldr f ([], 0)
where
f x (rs, n) = (2 * x : rs, if x == 5 then n + 1 else n)
The accumulated value is a pair of both the operations.
Notes:
Have a look at Beautiful folding. It shows a nice way how to make such computations composable.
You can use State for the same thing as well, by viewing each element as a stateful computation. This is a bit overkill, but certainly possible. In fact, any fold can be expressed as a sequence of State computations:
import Control.Monad
import Control.Monad.State
-- I used a slightly non-standard signature for a left fold
-- for simplicity.
foldl' :: (b -> a -> a) -> a -> [b] -> a
foldl' f z xs = execState (mapM_ (modify . f) xs) z
Function mapM_ first maps each element of xs to a stateful computation by modify . f :: b -> State a (). Then it combines a list of such computations into one of type State a () (it discards the results of the monadic computations, just keeps the effects). Finally we run this stateful computation on z.
How can I sample without replacement from a set of numbers ([1, 2, 3]) until I hit x?
My plan was to shuffle the list [1, 2, 3] and chop it at x:
-- chopAt 3 [2, 3, 1] == [2, 3]
-- chopAt 3 [2, 1, 3] == [2, 1, 3]
-- chopAt 3 [3, 1, 2] == [3]
chopAt _ [] = []
chopAt x (y:ys)
| x /= y = y : chopAt x ys
| otherwise = [y]
However I could not figure out how to shuffle the list (or understand Monads yet).
-- sample without replacement from [1, 2, 3] until one hits a 3
-- x <- shuffle [1, 2, 3]
-- print (chopAt 3 x)
main = do
-- shuffle [1, 2, 3]
print (chopAt 3 [1, 3, 2])
Use random and maybe even MonadRandom to implement your shuffles. A few good answers exist here
But that's really operational. Here's what's going on behind the scenes.
I.
Randomness is one of the first places in Haskell that you encounter and have to handle impurity---which seems offensive, because shuffles and samples seem so simple and don't feel like they ought to be bundled up with printing to a physical screen or launching nukes, but often purity == referentially transparent and referentially transparent randomness would be useless.
random = 9 -- a referentially transparent random number
So we need a different idea about randomness to make it pure.
II.
A typical "cheat" in scientific code used to enhance reproducibility—super important—is to fix your random seed of an experiment so that others can verify that they get exactly the same results every time your code is run. This is exactly referential transparency! Let's try it.
type Seed = Int
random :: Seed -> (Int, Seed)
random s = (mersenneTwisterPerturb s, splitSeed s)
where mersenneTwisterPerturb is a pseudorandom mapping from Seeds to Int and splitSeed is a pseudorandom mapping from Seeds to Seeds. Note that both of these functions are totally deterministic (and referentially transparent), so random is as well, but we can create an infinite, lazy pseudorandom stream like so
randomStream :: Seed -> [Int]
randomStram s = mersenneTwisterPerturb s : randomStream (splitSeed s)
Again, this stream is deterministic based on the Seed value, but an observer who sees only the stream and not the seed should be unable to predict its future values.
III.
Can we shuffle a list using a random stream of integers? Sure we can, by using modular arithmetic.
shuffle' :: [Int] -> [a] -> [a]
shuffle' (i:is) xs = let (firsts, rest) = splitAt (i `mod` length xs) xs
in (head rest) : shuffle' is (firsts ++ tail rest)
Or, to make it more self-contained, we can precompose our stream generating function to get
shuffle :: Seed -> [a] -> [a]
shuffle s xs = shuffle' (randomStream s) xs
another "seed consuming" referentially transparent "random" function.
IV.
So this seems to be a repeating trend. In fact, if you browse the module System.Random you'll see lots of functions like what we wrote above (I've specialized some type classes)
random :: (Random a) => StdGen -> (a, StdGen)
randoms :: (Random a) => StdGen -> [a]
where Random is the type class of things which can be generated randomly and StdGen is a kind of Seed. This is already enough actual working code to write the necessary shuffling function.
shuffle :: StdGen -> [a] -> [a]
shuffle g xs = shuffle' (randoms g) xs
and there's an IO function newStdGen :: IO StdGen which will let us build a random seed.
main = do gen <- newStdGen
return (shuffle gen [1,2,3,4,5])
But you'll notice something annoying: we need to keep varying the gen if we want to make different random permutations
main = do gen1 <- newStdGen
shuffle gen1 [1,2,3,4,5]
gen2 <- newStdGen
shuffle gen2 [1,2,3,4,5]
-- using `split :: StdGen -> (StdGen, StdGen)`
gen3 <- newStdGen
let (_, gen4) = split gen3
shuffle gen3 [1,2,3,4,5]
let (_, gen5) = split gen4
shuffle gen4 [1,2,3,4,5]
This means you'll either have to do lots of StdGen bookkeeping or stay in IO if you want different random numbers. This "makes sense" because of referential transparency again---a set of random numbers have to be random with respect to each other so you need to pass information from each random event on to the next.
It's really annoying, though. Can we do better?
V.
Well, generally what we need is a way to have a function take in a random seed then output some "randomized" result and the next seed.
withSeed :: (Seed -> a) -> Seed -> (a, Seed)
withSeed f s = (f s, splitSeed s)
The result type withSeed f :: Seed -> (a, Seed) is a fairly general result. Let's give it a name
newtype Random a = Random (Seed -> (a, Seed))
And we know that we can create meaningful Seeds in IO, so there's an obvious function to convert Random types to IO
runRandom :: Random a -> IO a
runRandom (Random f) = do seed <- newSeed
let (result, _) = f seed
return result
And now it feels like we've got something useful---a notion of a random value of type a, Random a is just a function on Seeds which returns the next Seed so that later Random values won't all be identical. We can even make some machinery to compose random values and do this Seed-passing automatically
sequenceRandom :: Random a -> Random b -> Random b
sequenceRandom (Random fa) (Random fb) =
Random $ \seed -> let (_aValue, newSeed) = fa seed in fb newSeed
but that's a little silly since we're just throwing away _aValue. Let's compose them such that the second random number actually depends materially on the first random value.
bindRandom :: Random a -> (a -> Random b) -> Random b
bindRandom (Random fa) getRb =
Random $ \seed -> let (aValue, newSeed) = fa seed
(Random fb) = getRb aValue
in fb newSeed
We also ought to note that we can do "pure" things to Random values, for instance, multiplying a random number by 2:
randomTimesTwo :: Random Int -> Random Int
randomTimesTwo (Random f) = Random $ \seed -> let (value, newSeed) = f seed
in (value*2, newSeed)
which we can abstract out as a Functor instance
instance Functor Random where
fmap f (Random step) = Random $ \seed -> let (value, newSeed) = step seed
in (f value, newSeed)
and now we can create cool random effects like Brownian motion
brownianMotion :: Random [Int]
brownianMotion =
bindRandom random $ \x ->
fmap (\rest -> x : map (+x) rest) brownianMotion
VI.
And this gets to the heart of the whole matter that I've been writing up to. Randomness can exist in the IO monad perfectly well, but it can also exist on its own as a simpler Random monad. We can write the instance immediately.
instance Monad Random where
return x = Random (\seed -> (x, seed))
rx >>= f = bindRandom rx f
And since it's a monad, we get free do notation
brownianMotion' = do x <- random
rest <- brownianMotion'
return $ x : map (+x) rest
and you could even get fancy and call runRandom a monad homomorphism, but that's a very different topic.
So, to recap
randomness in a referentially transparent language needs Seeds
carting Seeds are is annoying
there's a common pattern to "lifting" and "binding" random values which routes the Seeds around naturally
that pattern forms a monad
And the really short answer is that you probably want to be using random and maybe even MonadRandom to implement your shuffles. They'll come in handy for "sampling" generally.
Cheers!
Are you looking for permutations?
Also it seems that cropAt can be implemented via takeWhile. I personally prefer standard combinators over hand-made.
For shuffling a list, use the random-shuffle library:
import System.Random (newStdGen)
import System.Random.Shuffle (shuffle')
main = do
rng <- newStdGen
let xs = [1,2,3,4,5]
print $ shuffle' xs (length xs) rng
Bellow you may find some simple solution from beginning of my Haskell learning. If truth to be told, I'm still at the beginning or just slightly behind ;-)
import System.Random
import Control.Applicative
shuffle :: [a] -> IO [a]
shuffle [] = return []
shuffle lst = do
(e, rest) <- pickElem <$> getIx
(e:) <$> shuffle rest
where
getIx = getStdRandom $ randomR (1, length lst)
pickElem n = case splitAt n lst of
([], s) -> error $ "failed at index " ++ show n -- should never match
(r, s) -> (last r, init r ++ s)
Everyone seem to have encountered this at one point in time or another. This is my quick solution to a problem:
import System.Random
shuffle :: [a] -> IO [a]
shuffle [] = return []
shuffle xs = do randomPosition <- getStdRandom (randomR (0, length xs - 1))
let (left, (a:right)) = splitAt randomPosition xs
fmap (a:) (shuffle (left ++ right))
Note that the complexity is O(N^2), so this is pretty inefficient for larger lists. Other way is to implement Fisher-Yates shuffle by using mutable arrays (linear complexity):
import Data.Array.IO
import System.Random
swapElements_ :: (MArray a e m, Ix i) => a i e -> i -> i -> m ()
swapElements_ arr i j = do a <- readArray arr i
b <- readArray arr j
writeArray arr i b
writeArray arr j a
return ()
shuffle :: [a] -> IO [a]
shuffle xs = do let upperBound = length xs
arr <- (newListArray (1, upperBound) :: [a] -> IO (IOArray Int a)) xs
mapM_ (shuffleCycle arr) [2..upperBound]
getElems arr
where shuffleCycle arr i = do j <- getStdRandom (randomR (1, i))
swapElements_ arr i j
add this function to your code then call it like this shuffle (mkStdGen 5) [1,2,3,4,5]
import System.Random
shuffle gen [] = []
shuffle gen list = randomElem : shuffle newGen newList
where
randomTuple = randomR (0,(length list) - 1) gen
randomIndex = fst randomTuple
newGen = snd randomTuple
randomElem = list !! randomIndex
newList = take randomIndex list ++ drop (randomIndex+1) list
Or include it in your do block like that
main = do
r <- randomIO
str <- getLine
putStrLn (show (shuffle (mkStdGen r) str))