7
\$\begingroup\$

I have written a small desktop program nabeelomer/BingWallpapers in Haskell. This is my first time writing Haskell.

I was wondering how I can make the code use more functional programming features/idioms/patterns.

Any other suggestions on how to improve the code are also welcome.

-- Copyright (C) Nabeel Omer 2017
-- See the LICENSE file for the license
--

import Network.HTTP.Conduit
import System.Process
import qualified Data.ByteString.Lazy.Char8 as L8
import GHC.IO.Exception

main :: IO ()
main = do
    -- using http://muzzammil.xyz/git/bing/
    metadata <- get "http://cdn.muzzammil.xyz/bing/bing.php?format=text&cc=IN"

    -- Guaranteed by the API
    putStrLn $ (split '>' $ (lines $ L8.unpack metadata)!!1)!!1
    let url = (lines $ L8.unpack metadata)!!0
    picture <- get $ (split '>' url)!!1

    L8.writeFile "/dev/shm/Bing-Wallpaper" picture
    exitcode <- setWallpaper "/dev/shm/Bing-Wallpaper"

    print exitcode
    return ()

-- From StackOverflow
split :: Eq a => a -> [a] -> [[a]]
split d [] = []
split d s = x : split d (drop 1 y) where (x,y) = span (/= d) s

get :: String -> IO L8.ByteString
get url = simpleHttp url

setWallpaper :: String -> IO GHC.IO.Exception.ExitCode
setWallpaper uri = system $ "gsettings set org.gnome.desktop.background picture-uri file://" ++ uri
\$\endgroup\$
-1
\$\begingroup\$

Pattern matching instead of !!, inlining of single-use names where straightforward.

import Data.List.Split

main = do
  (_:picurl:_):(_:title:_):_ <- map (wordsBy (=='>')) . lines . L8.unpack
    <$> get "http://cdn.muzzammil.xyz/bing/bing.php?format=text&cc=IN"
  putStrLn title
  L8.writeFile "/dev/shm/Bing-Wallpaper" =<< get picurl
  print =<< setWallpaper "/dev/shm/Bing-Wallpaper"
\$\endgroup\$
  • \$\begingroup\$ Can you please explain how the map (wordsBy (=='>')) . lines . L8.unpack <$> get part works? \$\endgroup\$ – 1 -_- Jun 27 '17 at 19:08
  • \$\begingroup\$ (<$>) :: Functor f => (a -> b) -> f a -> f b is an infix synonym for fmap, and fmap f x is like x >>= return . f for monads. map applies Data.List.Split's wording of split to both lines where you'd do it to each manually. (f . g) x = f (g x) and . has higher precedence than <$>, so all of the left of <$> is fmaped over its right. Feel free to keep your comments around, of course. \$\endgroup\$ – Gurkenglas Jun 27 '17 at 21:08
  • 4
    \$\begingroup\$ You have presented an alternative solution, but only slightly reviewed the code. Please explain your reasoning (how your solution works and why it is better than the original) in the post, not in the comments, so that the author and other readers can learn from your thought process. \$\endgroup\$ – Zeta Jun 29 '17 at 7:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.