Modifying a random String stored in the clipboard I wrote a simple program, that will make a string 'noisy' if the clipboard contains one.
What disappoints me, is that I should manually check what I got from 
getClipboardString — in the Nothing case, we simply return from program, otherwise we modify the string. Is there a better way to do this kind of check?

import Data.Char (toUpper)
import System.Random (randomIO)
import System.Clipboard (setClipboardString, getClipboardString)
import Control.Monad (join)

main :: IO ()
main = do 
 join $ fmap (test doNoise) getClipboardString
 where
 test :: (String -&gt; IO ()) -&gt; (Maybe String) -&gt; IO ()
 test _ Nothing = return ()
 test f (Just s) = f s

 doNoise :: String -&gt; IO ()
 doNoise s = do
  capsed &lt;- (sequence $ map randCap s)
  setClipboardString capsed

 randCap :: Char -&gt; IO Char
 randCap x = fmap ($ x) $ fmap choice (randomIO :: IO Bool)

 choice :: Bool -&gt; (Char -&gt; Char)
 choice x = if x then toUpper else id
main :: IO ()
main = traverse_ doNoise =&lt;&lt; getClipboardString where
 doNoise = setClipboardString &lt;=&lt; traverse randCap
 randCap x = bool id toUpper &lt;$&gt; (randomIO :: IO Bool) &lt;*&gt; pure x


Edit: Each change was arrived at through pattern-matching from my experience; compact code is usually easier to work with further. Looking at this again makes me think there ought to be a more lensy solution, one that fuses getting and setting, and indeed:

main = modifyClipboardString =&lt;&lt;
  zipWith (bool id toUpper) &lt;$&gt; getRandoms


We are fortunate to not actually need side effects depending on clipboard contents, but if we did, I would recommend writing a monadic variant of modifyClipboardString.