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 -> IO ()) -> (Maybe String) -> IO ()
test _ Nothing = return ()
test f (Just s) = f s
doNoise :: String -> IO ()
doNoise s = do
capsed <- (sequence $ map randCap s)
setClipboardString capsed
randCap :: Char -> IO Char
randCap x = fmap ($ x) $ fmap choice (randomIO :: IO Bool)
choice :: Bool -> (Char -> Char)
choice x = if x then toUpper else id
1 Answer 1
main :: IO ()
main = traverse_ doNoise =<< getClipboardString where
doNoise = setClipboardString <=< traverse randCap
randCap x = bool id toUpper <$> (randomIO :: IO Bool) <*> 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 lens
y solution, one that fuses getting and setting, and indeed:
main = modifyClipboardString =<<
zipWith (bool id toUpper) <$> 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
.
-
2\$\begingroup\$ That's a compact solution :) Could you elaborate how you got to this and how it's better than the original code? \$\endgroup\$dfhwze– dfhwze2019年06月11日 19:26:17 +00:00Commented Jun 11, 2019 at 19:26
-
4\$\begingroup\$ You have presented an alternative solution, but haven't reviewed the code. Please explain your reasoning (how your solution works and why it is better than the original) so that the author and other readers can learn from your thought process. Please read Why are alternative solutions not welcome? \$\endgroup\$2019年06月11日 19:26:24 +00:00Commented Jun 11, 2019 at 19:26
-
\$\begingroup\$ Some thoughts that I have: first, that I should use hoogle more thoroughly (I didn't know of
traverse
,traverse_
andbool
); second, that I should read my code more closely, because I missedjoin $ fmap == (=<<)
. Anyway, elegant solution, will upvote later, not enough rep right now \$\endgroup\$Stuthedian– Stuthedian2019年06月12日 05:59:13 +00:00Commented Jun 12, 2019 at 5:59