If I have a function that shuffles a "deck of cards", how do I use the State Monad to iterate through a defined set number of shuffles and then return a result?
For example I have the following function that will do 1 shuffle of the deck then return a specific card:
step :: State [String] String
step = do
  modify shuffle
  deck <- get
  pure $ bestCard deck
What I would like to be able to do is iterate through the state changes 5 times before I return the value.
What I have tried is this:
steps :: Int -> State [String] String
steps n = case n of
  0 -> do
    deck <- get
    pure $ bestCard deck
  _ -> do
    modify shuffle
    steps (n - 1)
but that looks far from being the correct way of doing it, even though it works.
NB. I am aware this can be done without using State Monad but I am trying to use this example to learn how to use State.
edit:
Thanks to @Koterpillar, I can use replicateM to get what I want.
evalState (replicateM n $ modify shuffle >> get >>= pure . bestCard)
The most succinct way to do it is replicateM_, which repeats a monadic action a specified number of times and discards the result:
replicateM_ 5 $ modify shuffle
Because State is a monad, you only have to care about repeating an action, not specifically working with State. I found the above function by searching Hoogle for the signature of the function I wanted:
Monad m => Int -> m a -> m ()
Note that the result doesn't even require a monad, just an applicative:
replicateM_ :: Applicative m => Int -> m a -> m ()
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With