2016-04-26 28 views
0

我想使用taffybar作爲我的狀態欄(使用Dyre框架,因此配置是代碼)。它有一個可以顯示網絡接口統計信息的小部件。在默認配置下,這個小部件在編譯時需要String。我希望它動態地爲每個(非回送)接口創建一個小部件。Haskell:從FS讀取到「動態」創建taffybar中的小部件

這是我到目前爲止有:

listNetworkDevices :: IO [String] 
listNetworkDevices = fmap (map takeBaseName) $ getDirectoryContents "/sys/class/net/" 

filterOutLoopback :: [String] -> [String] 
filterOutLoopback = filter (\y -> not (elem y ["", ".", "lo"])) 

netDevList :: IO [String] 
netDevList = fmap filterOutLoopback listNetworkDevices 

... 

let nets = fmap (fmap (netMonitorNew 1)) netDevList 
    ... 
defaultTaffybar defaultTaffybarConfig { 
    ... 
    endWidgets = [ tray, clock, mem, cpu] ++ nets ++ [ bat ] 
} 

在這一點上,我倒在以下編譯器錯誤:

Couldn't match expected type ‘[IO gtk-0.14.2:Graphics.UI.Gtk.Types.Widget]’ 
      with actual type ‘IO [IO gtk-0.14.2:Graphics.UI.Gtk.Types.Widget]’ 

總體來說,這一錯誤是有道理的,因爲我正在做每String中有一個IO Widget。所以IO [String]變成IO [IO Widget]

我不明白的是如何避免這樣做。很明顯,我一定在某個時候出了問題,但我看不到在哪裏。我甚至不知道如何用言語來解決問題。我會很高興任何指針!

相關材料:

編輯:完整列表:

import System.Taffybar 
import System.Taffybar.Systray 
import System.Taffybar.Pager 
import System.Taffybar.TaffyPager 
import System.Taffybar.SimpleClock 
import System.Taffybar.Battery 
import System.Taffybar.NetMonitor 
import System.Taffybar.Weather 
import System.Taffybar.Widgets.PollingBar 
import System.Taffybar.Widgets.PollingGraph 
import System.Information.Memory 
import System.Information.CPU 
import System.Directory (getDirectoryContents) 
import System.FilePath (takeBaseName) 
import Control.Monad 

memCallback = do 
    mi <- parseMeminfo 
    return [memoryUsedRatio mi] 

cpuCallback = do 
    (userLoad, systemLoad, totalLoad) <- cpuLoad 
    return [totalLoad, systemLoad] 

listNetworkDevices :: IO [String] 
listNetworkDevices = fmap (map takeBaseName) $ getDirectoryContents "/sys/class/net/" 

filterOutLoopback :: [String] -> [String] 
filterOutLoopback = filter (\y -> not (elem y ["", ".", "lo"])) 

netDevList :: IO [String] 
netDevList = fmap filterOutLoopback listNetworkDevices 

myPagerConfig = defaultPagerConfig {} 

main = do 
    let memCfg = defaultGraphConfig { graphDataColors = [(1, 0, 0, 1)] } 
     cpuCfg = defaultGraphConfig { graphDataColors = [ (0, 1, 0, 1) 
                 , (1, 0, 1, 0.5) 
                 ] 
            } 
     clock = textClockNew Nothing "<span fgcolor='orange'>%a %b %d %H:%M</span>" 1 
     pager = taffyPagerNew myPagerConfig 
     mem = pollingGraphNew memCfg 1 memCallback 
     cpu = pollingGraphNew cpuCfg 1 cpuCallback 
     bat = textBatteryNew "$percentage$% $time$" 1 
     tray = systrayNew 

     --nets = [ netMonitorNew 1 "wlp0s2" ] 
     nets = fmap (fmap (netMonitorNew 1)) netDevList 

    defaultTaffybar defaultTaffybarConfig { startWidgets = [ pager ] 
             , endWidgets = [ tray, clock, mem, cpu] ++ nets ++ [ bat ] 
             } 

編輯:錯誤消息:

.config/taffybar/taffybar.hs: 
    Couldn't match expected type ‘[IO 
            gtk-0.14.2:Graphics.UI.Gtk.Types.Widget]’ 
       with actual type ‘IO [IO gtk-0.14.2:Graphics.UI.Gtk.Types.Widget]’ 
    In the first argument of ‘(++)’, namely ‘nets’ 
    In the second argument of ‘(++)’, namely ‘nets ++ [bat]’ 
+0

可以添加完整的錯誤消息和引發錯誤的完整源代碼函數。另外我認爲你的源代碼是不正確的 - 'let'語句在文件中沒有意義。 – epsilonhalbe

+0

@epsilonhalbe:完成。 – McEnroe

+0

我沒有徹底研究過代碼,但我的猜測是memcallback或cpucallback是錯誤的(添加類型簽名)或'nets ='應該是'nets <-' – epsilonhalbe

回答

1

我沒有測試過這是我平時做的,因爲我沒有安裝這臺機器上taffybar,但我懷疑以下的小變化應該可以幫助你取得進步:

main = do 
    let memCfg = defaultGraphConfig { graphDataColors = [(1, 0, 0, 1)] } 
     cpuCfg = defaultGraphConfig { graphDataColors = [ (0, 1, 0, 1) 
                 , (1, 0, 1, 0.5) 
                 ] 
            } 
     clock = textClockNew Nothing "<span fgcolor='orange'>%a %b %d %H:%M</span>" 1 
     pager = taffyPagerNew myPagerConfig 
     mem = pollingGraphNew memCfg 1 memCallback 
     cpu = pollingGraphNew cpuCfg 1 cpuCallback 
     bat = textBatteryNew "$percentage$% $time$" 1 
     tray = systrayNew 

    -- this line is the only one that changed 
    nets <- fmap (fmap (netMonitorNew 1)) netDevList 

    defaultTaffybar defaultTaffybarConfig { startWidgets = [ pager ] 
             , endWidgets = [ tray, clock, mem, cpu] ++ nets ++ [ bat ] 
             } 

可能還有其他問題,但這應該解決問題中描述的問題。

當然還有很多風格上的變化可以/應該做出來,例如,我想我可能會這樣寫最後兩行代碼:

nets <- netDevList 
    defaultTaffybar ... { ..., endWidgets = ... ++ map netMonitorNew nets ++ ... } 
+0

謝謝,這確實解決了這個問題。你認爲你可以用一兩句話評論我最初做了什麼(錯誤)?我仍然試圖開發語言來討論Haskell代碼。 – McEnroe

+0

@McEnroe您可能會喜歡sigfpe的[IO介紹](http://blog.sigfpe.com/2007/11/io-monad-for-people-who-simply-dont.html)。 –

相關問題