我想使用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]
。
我不明白的是如何避免這樣做。很明顯,我一定在某個時候出了問題,但我看不到在哪裏。我甚至不知道如何用言語來解決問題。我會很高興任何指針!
相關材料:
- endWidgets文檔:https://hackage.haskell.org/package/taffybar-0.4.6/docs/System-Taffybar.html#v:endWidgets
- netMonitorNew文檔:https://hackage.haskell.org/package/taffybar-0.4.6/docs/System-Taffybar-NetMonitor.html#v:netMonitorNew
- 來源GitHub上:https://github.com/travitch/taffybar/tree/master/src/System/Taffybar
編輯:完整列表:
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]’
可以添加完整的錯誤消息和引發錯誤的完整源代碼函數。另外我認爲你的源代碼是不正確的 - 'let'語句在文件中沒有意義。 – epsilonhalbe
@epsilonhalbe:完成。 – McEnroe
我沒有徹底研究過代碼,但我的猜測是memcallback或cpucallback是錯誤的(添加類型簽名)或'nets ='應該是'nets <-' – epsilonhalbe