<div>Will need more experience before discerning between beauty and ridiculousness in Haskell code, but your version is helpful nonetheless. Can see that separating out the dice rolls at least makes a big difference. And since there's only one bind, it's readable enough without do syntax. Thank you for your suggestions!<br></div><div><br></div><div>Regards,<br></div><div>Andrea<br></div><div><br></div><div class="protonmail_signature_block "><div class="protonmail_signature_block-user protonmail_signature_block-empty"><br></div><div class="protonmail_signature_block-proton ">Sent with <a href="https://protonmail.com">ProtonMail</a> Secure Email.<br></div></div><div><br></div><blockquote class="protonmail_quote" type="cite"><div>-------- Original Message --------<br></div><div>Subject: Re: [Haskell-cafe] Feedback on use of State monad<br></div><div>Local Time: July 14, 2017 3:22 AM<br></div><div>UTC Time: July 14, 2017 8:22 AM<br></div><div>From: monkleyon@gmail.com<br></div><div>To: haskell-cafe@haskell.org<br></div><div><br></div><div>On 2017-07-13 23:29, Atrudyjane via Haskell-Cafe wrote:<br></div><div>> runRolls :: State RollsState RollsValue<br></div><div>> runRolls = do<br></div><div>>   (l, s, c, sg, xs) <- get<br></div><div>>   if (s >= l) then<br></div><div>>     return (c, reverse xs)<br></div><div>>   else<br></div><div>>     do<br></div><div>>       let (d, ng) = randomR (1, 6) sg<br></div><div>>       put (l, s + d, c + 1, ng, intToDie d : xs)<br></div><div>>       runRolls<br></div><div>><br></div><div>> rollsCountState :: Int -> IO ()<br></div><div>> rollsCountState n = print $ evalState (runRolls) (n, 0, 0, mkStdGen 0, [])<br></div><div>><br></div><div>> I"m wondering if that "do" block under the else is a not so great <br></div><div>> stylistic choice. If the "let" and "put" is moved above the "if", then <br></div><div>> that"s just an unnecessary call at the end. Or is it just the nature <br></div><div>> of running inside a monad?<br></div><div><br></div><div>It is the nature of running inside a monad. But at the same time, <br></div><div>runRolls contains the implementation of two things. Which, to a purist <br></div><div>like me, would be one too many. Pulling one of them out into a second <br></div><div>function already makes this one much nicer. But there are other, more <br></div><div>pressing stylistic choices to make. Namely to use records and mnemonic <br></div><div>names. Here is an adapted version taken to more beauty and then beyond <br></div><div>into ridiculousness:<br></div><div><br></div><div> {-# LANGUAGE RecordWildCards , MultiWayIf #-}<br></div><div> <br></div><div> […]<br></div><div><br></div><div> rollsCountState :: Int -> IO ()<br></div><div> rollsCountState rollLimit = print $ evalState runRolls initialRollState<br></div><div> where<br></div><div> runRolls = get >>= \RollsState{..} -><br></div><div> if | rollSum >= rollLimit -> pure (rollCount, reverse rolledDice)<br></div><div> | otherwise            -> modify rollDice >> runRolls<br></div><div><br></div><div>The “ideal” version is probably somewhere in between. Maybe with one of <br></div><div>the many whileM or untilM implementations thrown in that everyone keeps <br></div><div>reinventing.<br></div><div><br></div><div>Cheers,<br></div><div>MarLinn<br></div><div><br></div><div>_______________________________________________<br></div><div>Haskell-Cafe mailing list<br></div><div>To (un)subscribe, modify options or view archives go to:<br></div><div>http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe<br></div><div>Only members subscribed via the mailman list are allowed to post.<br></div></blockquote><div><br></div>