Haskell XMonad 配置使用 readProcess

Haskell XMonad configuration using readProcess

我在没有真正理解的情况下尝试配置 XMonad Haskell 语法。

我 运行 一个带有 xmonad 的 gnome 会话。我想按 mod-p 来 切换 gnome 面板:

我以为这样就可以了:

startgpanel :: X ()
startgpanel = do
  gp <- readProcess "pidof" ["gnome-panel"] ""
     if (length gp)
     then spawn "killall gnome-panel"
     else spawn "gnome-panel"

  ...
 ((myModMask, xK_g), startgpanel)
  ...

但是我得到一个错误:

xmonad.hs:169:12:
    Couldn't match expected type âX (t0 a0)â
                with actual type âIO Stringâ
    In a stmt of a 'do' block:
      gp <- readProcess "pidof" ["gnome-panel"] ""
    In the expression:
      do { gp <- readProcess "pidof" ["gnome-panel"] "";
           if (length gp) then
               spawn "killall gnome-panel"
           else
               spawn "gnome-panel" }

我不是很了解Monad的概念,我只是想 做一些IO,但是看起来很复杂...

您需要将您的 IO 操作包装在 liftIO 到 运行 X monad 中。 此外,您不能仅将 length 的结果用作 if 语句的 Bool,因为它 returns 和 Int:

startgpanel :: X ()
startgpanel = do
  gp <- liftIO $ readProcess "pidof" ["gnome-panel"] ""
  if (length gp > 0)
    then spawn "killall gnome-panel"
    else spawn "gnome-panel"

正如其他人提到的,您需要使用 liftIO

另请参考这个SO问题的讨论:

How do I use the output of readProcess in an xmonad keybinding?

您可能需要使用 readProcessWithInput,而不是 readProcess

由于 xmonad 对进程的所有处理,我建议您将整个该死的逻辑移到 shell;为这个操作绑定一个键:

spawn "pidof gnome-panel && killall gnome-panel || gnome-panel"

你看,没有 do