0

I am trying to write a custom functionality for my xmonad window manager. I am not very comfortable with functional programming yet and still am trying to wrap my head around it. In python etc. this would be an easy task for me.

I have the light utility installed on my system. $ light -S 40.0 for example sets the backgroundlight to 40% brightness. $ light -G returns the current brightness.

I have a list with values I like to advance through (and a start index)

screenBrightnessIndex :: Int
screenBrightnessIndex = 9

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

I wrote the following function:

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)

It should check the current output of "light -G" and find the index. Then it either increases or deceases the index by the provided value.

Calling the functions should work like this:

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

My problem is that I don't understand how I would get the current screen brightness as a float. I tried the following (with XMonad.Util.Run):

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

But this gives me errors. I know it has to do with the fact that the function return a MonadIO String and not a String. I also found several answers for similar problems. Most of them said it isn't possible to extract a String because of exceptions that may occur in Monads and security. But Monads are still very confusing to me. Also I don't believe there is a programming problem without a solution. I just don't know how.

I hope I explained my problem sufficiently. It would be nice if someone could help me with this. It would be even better if there is a better/more simple approach to the problem I am not thinking of. Thanks alot.

FLKNB
  • 3
  • 3
  • I think you should break this down into multiple problems / questions. And then it's easier for you to search existing solutions. Basically you need to parse a float value - https://stackoverflow.com/questions/27121575/how-to-parse-a-float-number-input-in-haskell and then to find the index https://stackoverflow.com/questions/4272791/how-to-find-the-index-of-an-element-in-a-list/4272801 – Chris Stryczynski Mar 28 '21 at 11:48

1 Answers1

0

The signatures can help here:

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

read expects a String type and not a MonadIO m => m StringSource type. So your goal should be to get a String from that first and then pass it to read. This might be usefull: https://wiki.haskell.org/Introduction_to_Haskell_IO/Actions

Chris Stryczynski
  • 30,145
  • 48
  • 175
  • 286