0
focusedWindow = spawn ("notify-send \"Focused on " <> readWindowName ++ "\"")

readWindowName :: String
readWindowName = let wn = runProcessWithInput "xdotool" ["getactivewindow getwindowname"] "" in wn

I'm trying to get the output of the process xdotool using the function runProcessWithInput, but the resulting error pops up:

xmonad.hs:236:121: error:
    • Couldn't match type ‘[Char]’ with ‘Char’
      Expected: String
        Actual: [String]
    • In the expression: wn
      In the expression:
        let wn = runProcessWithInput "xdotool" [...] "" in wn
      In an equation for ‘readWindowName’:
          readWindowName
            = let wn = runProcessWithInput "xdotool" ... "" in wn
    |
236 |                         readWindowName = let wn = runProcessWithInput "xdotool" ["getactivewindow getwindowname"] "" in wn
    |                                                                                                                         ^^   

readWindowName needs to be a String as it is concatenated into a string inside spawn in focusedWindow. However, the function returns a [String], which is where I'm stuck at. Tried unlines, but I can't seem to make it work.


I also tried different methods of the same function, but they also don't work:

readWindowName' :: String
readWindowName' = do
    wn <- runProcessWithInput "xdotool" ["getactivewindow getwindowname"] ""
    return wn

readWindowName'' :: String
readWindowName'' = let wn = runProcessWithInput "xdotool" ["getactivewindow getwindowname"] "" 
                       wn' = unlines wn
                   in wn'

readWindowName'' gives a different error:

xmonad.hs:236:51: error:
    • No instance for (MonadIO [])
        arising from a use of ‘runProcessWithInput’
    • In the expression:
        runProcessWithInput "xdotool" ["getactivewindow getwindowname"] ""
      In an equation for ‘wn’:
          wn
            = runProcessWithInput
                "xdotool" ["getactivewindow getwindowname"] ""
      In the expression:
        let
          wn = runProcessWithInput "xdotool" [...] ""
          wn' = unlines wn
        in wn'
    |
236 |                         readWindowName = let wn = runProcessWithInput "xdotool" ["getactivewindow getwindowname"] ""
    |              

I did research about many others' exact problem (namely here, here, and here), and I found that in the source code of runProcessWithInput, it uses the return statement, which (I believe) might be the problem in my code, mentioned in this answer:

return :: Monad m => a -> m a is used to wrap a value (of type a) in a monad.

Is there any way to get around this or a different function that I haven't discovered yet other than editing the runProcessWithInput source code?

Anapal
  • 15
  • 4
  • 3
    `runProcessWithInput` actually returns an `m String` for any `m` that can perform IO, indicating that its value could change with time (making it impure). You can't just use it as a `String` because it might not be the same the next time you use it. Changing the type of `readWindowName` to `IO String` should do the trick. – fluffyyboii Jul 07 '23 at 15:17
  • @fluffyyboii That certainly makes sense, thanks. Changed the type to `IO String` and the initial error is gone, but the function still needs to be a `String` type. I still can't quite grasp on how to use this type in order to concatenate it into a string; I read answers ([1](https://stackoverflow.com/a/16197901/19234665) [2](https://stackoverflow.com/a/11230235/19234665)) relating to this, but my mind isn't clicking. – Anapal Jul 07 '23 at 16:26
  • 3
    You might need something like `do wn <- readWindowName ; spawn ("notify-send \"Focused on " ++ wn ++ "\"")`. The type of this will be `IO ()`. Note how IO is viral: if you use something IO-based, you need that definition to have an IO type. This is how Haskell forces the programmer to mark all the code parts that do IO in their types. – chi Jul 07 '23 at 16:41

1 Answers1

0

Okay, after some time off this problem, it turns out that the solution was simpler than I thought.

focusedWindow = do
    wn <- runProcessWithInput "xdotool" ["getactivewindow", "getwindowname"] ""
    spawn ("notify-send 'Focused on " ++ wn ++ "'")
Anapal
  • 15
  • 4