如何在haskell中使用XMonad.Util.Run runProcessWithInput输出查找列表的索引?

问题描述

我正在尝试为我的 xmonad 窗口管理器编写自定义功能。 我对函数式编程还不是很满意,并且仍在努力解决它。在 python 等中,这对我来说是一项简单的任务。

我的系统上安装了 light 实用程序。 $ light -S 40.0 例如将背景灯设置为 40% 的亮度。 $ light -G 返回当前亮度。

我有一个列表,其中包含我喜欢前进的值(以及一个起始索引)

screenBrightnessIndex :: Int
screenBrightnessIndex = 9

screenBrightnesssteps :: [Float]
screenBrightnesssteps = [0,0.1,0.2,0.4,0.8,2,5,10,20,40,60,80,100]

我编写了以下函数

changeBrightness :: Int -> Int
changeBrightness i
  | sBI + i < 0 = 0
  | sBI + i > length screenBrightnesssteps - 1 = length screenBrightnesssteps - 1
  | otherwise = sBI + i
  where
    sBI = fromMaybe screenBrightnessIndex (elemIndex (???) screenBrightnesssteps)

它应该检查“light -G”的当前输出并找到索引。然后按提供的值增加或减少索引。

调用函数应该是这样的:

spawn $ "light -S " ++ show (screenBrightnesssteps !! changeBrightness 1)
spawn $ "light -S " ++ show (screenBrightnesssteps !! changeBrightness -1)

我的问题是我不明白如何将当前屏幕亮度设为浮动。 我尝试了以下(使用 XMonad.Util.Run):

read (runProcessWithInput "light" ["-G"] "") :: Float

但这给了我错误。我知道这与函数返回 Monadio 字符串而不是字符串的事实有关。我还找到了几个类似问题的答案。他们中的大多数人表示,由于 Monads 和安全性中可能发生的异常,不可能提取 String。但是 Monads 对我来说仍然很困惑。此外,我不相信没有解决方案就存在编程问题。我只是不知道如何。

我希望我能充分解释我的问题。 如果有人能帮我解决这个问题,那就太好了。 如果有更好/更简单的方法解决我没有想到的问题,那就更好了。 非常感谢。

解决方法

签名可以在这里提供帮助:

runProcessWithInput :: MonadIO m => FilePath -> [String] -> String -> m String
read :: Read a => String -> a

read 需要 String 类型而不是 MonadIO m => m StringSource 类型。因此,您的目标应该是首先从中获取 String,然后将其传递给 read。这可能很有用:https://wiki.haskell.org/Introduction_to_Haskell_IO/Actions