0

I'm trying to adjust my key bindings in Xmonad depending on the number of screen (physical screens/monitors) I am currently using. Somehow I am failing with this task, probably due to my lack of Haskell knowledge.

Somewhere in my xmonad.hs file I define my keybindings:

myKeys =
    [ ...
    , ...
    , ("M-x", showSet1)
    , ...
    ]

So far I defined showSet1 elsewhere in the file (abc is a placeholder for the actual definition:

showSet1 = abc

Then I used myKeys like this:

main :: IO ()
main = xmonad
     . ewmhFullscreen
     ...
     $ myConfig

myConfig = def
    { modMask = myModMask
    , ...
    } `additionalKeysP` myKeys

This worked perfectly so far, but now I want to adjust showSet1 depending on the number of screens. I found this thread and from there use the following to get the number of screens:

numScreens :: X Int
numScreens = withDisplay (io.fmap length.getScreenInfo)

My plan was to use the following to define showSet1:

showSet1 = if numScreens == 4
    then abc
    else xyz

When compiling xmonad, I get the following error:

    • No instance for (Eq (X Int)) arising from a use of ‘==’
    • In the expression: numScreens == 4
      In the expression:
        if numScreens == 4 then
            abc
        else
            xyz

If I understand that correctly, numScreens is of type X Int and I cannot compare that to 4. Any idea how I can do that? I have tried a lot of things, including playing with the function screenCount, but nothing worked so far.

schuam
  • 3
  • 1
  • Not related to your problem, but `numScreens` is defined various places in the contrib libraries, too; e.g. [`countScreens`](https://hackage.haskell.org/package/xmonad-contrib-0.17.1/docs/XMonad-Layout-IndependentScreens.html#v:countScreens). – Daniel Wagner Aug 15 '23 at 15:58
  • @DanielWagner I did see at least one of these definitions, but somehow could not make them work. I don't really know why. I went with the answer from arrowd which help right away, otherwise I would have looked more into the numScreens definitions. – schuam Aug 19 '23 at 00:11

1 Answers1

1

Since you're getting the number of screens from X, it isn't a pure computation. Hence, it is a X Int rather than plain Int. Depending on what asd and xyz are, this might help:

showSet1 = do
  ns <- numScreens
  if ns == 4
    then abc
    else xyz
arrowd
  • 33,231
  • 8
  • 79
  • 110
  • Thanks a lot @arrowd! That solved my problem. I just coundn't figure out how to get rid of the "X" in `X Int`. Maybe I should actually spend some time learning Haskell. – schuam Aug 19 '23 at 00:07
  • To put it very simple, when you do `x <- y` where `y` is of type `Foo Bar`, you get `Bar` in `x`. But you can only write `x <- y` inside a `do` expression. The whole `do` expression then would be of type `Foo a`, where `a` can be anything. Of course, my simplification is on the edge of incorrectness, but it will do for the sake of editing XMonad configs. You can read about Monads in details here: https://stackoverflow.com/q/44965/637669 – arrowd Aug 20 '23 at 09:22