Как найти индекс списка с выводом XMonad.Util.Run runProcessWithInput в haskell?

Я пытаюсь написать пользовательскую функциональность для моего оконного менеджера xmonad. Я еще не очень хорошо разбираюсь в функциональном программировании и все еще пытаюсь понять это. В python и т. д. для меня это было бы легкой задачей.

В моей системе установлена ​​легкая утилита. $ 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)

Он должен проверить текущий выход света -G и найти индекс. Затем он либо увеличивает, либо уменьшает индекс на указанное значение.

Вызов функций должен работать следующим образом:

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

Моя проблема в том, что я не понимаю, как получить текущую яркость экрана в виде числа с плавающей запятой. Я пробовал следующее (с XMonad.Util.Run):

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

Но это дает мне ошибки. Я знаю, что это связано с тем, что функция возвращает строку MonadIO, а не строку. Я также нашел несколько ответов для подобных проблем. Большинство из них сказали, что невозможно извлечь строку из-за исключений, которые могут возникнуть в монадах и безопасности. Но монады все еще очень смущают меня. Также я не верю, что существует проблема программирования без решения. Я просто не знаю как.

Надеюсь, я достаточно объяснил свою проблему. Было бы неплохо, если бы кто-нибудь помог мне с этим. Было бы еще лучше, если бы был лучший/более простой подход к проблеме, о которой я не думаю. Большое спасибо.


person FLKNB    schedule 28.03.2021    source источник
comment
Я думаю, вы должны разбить это на несколько проблем/вопросов. И тогда вам будет проще искать существующие решения. В основном вам нужно проанализировать значение с плавающей запятой - stackoverflow.com/questions/27121575/, а затем найти индекс stackoverflow.com/questions/4272791/   -  person Chris Stryczynski    schedule 28.03.2021


Ответы (1)


Здесь могут помочь подписи:

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

person Chris Stryczynski    schedule 28.03.2021