BingWallpapers: Fetches and applies the image of the day from Bing as the wallpaper











up vote
5
down vote

favorite












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









share|improve this question




























    up vote
    5
    down vote

    favorite












    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









    share|improve this question


























      up vote
      5
      down vote

      favorite









      up vote
      5
      down vote

      favorite











      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









      share|improve this question















      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






      beginner haskell http






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Jun 26 '17 at 5:55

























      asked Jun 25 '17 at 20:38









      1 -_-

      265




      265






















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          0
          down vote













          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"





          share|improve this answer





















          • Can you please explain how the map (wordsBy (=='>')) . lines . L8.unpack <$> get part works?
            – 1 -_-
            Jun 27 '17 at 19:08










          • (<$>) :: 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.
            – Gurkenglas
            Jun 27 '17 at 21:08






          • 1




            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.
            – Zeta
            Jun 29 '17 at 7:05











          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














           

          draft saved


          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f166622%2fbingwallpapers-fetches-and-applies-the-image-of-the-day-from-bing-as-the-wallpa%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          0
          down vote













          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"





          share|improve this answer





















          • Can you please explain how the map (wordsBy (=='>')) . lines . L8.unpack <$> get part works?
            – 1 -_-
            Jun 27 '17 at 19:08










          • (<$>) :: 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.
            – Gurkenglas
            Jun 27 '17 at 21:08






          • 1




            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.
            – Zeta
            Jun 29 '17 at 7:05















          up vote
          0
          down vote













          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"





          share|improve this answer





















          • Can you please explain how the map (wordsBy (=='>')) . lines . L8.unpack <$> get part works?
            – 1 -_-
            Jun 27 '17 at 19:08










          • (<$>) :: 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.
            – Gurkenglas
            Jun 27 '17 at 21:08






          • 1




            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.
            – Zeta
            Jun 29 '17 at 7:05













          up vote
          0
          down vote










          up vote
          0
          down vote









          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"





          share|improve this answer












          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"






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Jun 27 '17 at 13:53









          Gurkenglas

          2,728511




          2,728511












          • Can you please explain how the map (wordsBy (=='>')) . lines . L8.unpack <$> get part works?
            – 1 -_-
            Jun 27 '17 at 19:08










          • (<$>) :: 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.
            – Gurkenglas
            Jun 27 '17 at 21:08






          • 1




            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.
            – Zeta
            Jun 29 '17 at 7:05


















          • Can you please explain how the map (wordsBy (=='>')) . lines . L8.unpack <$> get part works?
            – 1 -_-
            Jun 27 '17 at 19:08










          • (<$>) :: 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.
            – Gurkenglas
            Jun 27 '17 at 21:08






          • 1




            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.
            – Zeta
            Jun 29 '17 at 7:05
















          Can you please explain how the map (wordsBy (=='>')) . lines . L8.unpack <$> get part works?
          – 1 -_-
          Jun 27 '17 at 19:08




          Can you please explain how the map (wordsBy (=='>')) . lines . L8.unpack <$> get part works?
          – 1 -_-
          Jun 27 '17 at 19:08












          (<$>) :: 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.
          – Gurkenglas
          Jun 27 '17 at 21:08




          (<$>) :: 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.
          – Gurkenglas
          Jun 27 '17 at 21:08




          1




          1




          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.
          – Zeta
          Jun 29 '17 at 7:05




          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.
          – Zeta
          Jun 29 '17 at 7:05


















           

          draft saved


          draft discarded



















































           


          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f166622%2fbingwallpapers-fetches-and-applies-the-image-of-the-day-from-bing-as-the-wallpa%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Morgemoulin

          Scott Moir

          Souastre