Managehook which only shifts window if workspace is empty

I'm trying to write a Managehook that only shifts a window to workspace if that workspace is empty. But I'm quickly realising I don't have a good enough grasp of Xmonad types, and Haskell monads in general, to get it to work. So far, the closest I think I've got is the following: myManageHook = [ className =? "mutt" --> doShiftEmpty "email" ] where doShiftEmpty t = when (isEmpty t) (doShift t) isEmpty t = do wsl <- gets $ W.workspaces . windowset let mws = find (\ws -> W.tag ws == t) wsl return $ maybe True (isNothing . W.stack) mws which throws a type error: "Couldn't match expected type `Bool' with actual type `m0 Bool' In the return type of a call of `isEmpty'" I think I vaguely understand the problem, namely that "when" expects a Bool as its first argument, whereas the "return" in isEmpty returns a Bool wrapped inside a monad. But removing the "return" just throws a more confusing type error. Clearly, I'm way out of my depth here, and am doing little better than cargo cult programming. Can someone who understands these things properly explain where I'm going wrong here? More generally, is there a tutorial explaining the Xmonad types and data structures, and how they go together to make up Xmoand? I've been working through some basic Haskell tutorials, but there's still quite a step from understanding a little Haskell, to understanding enough of how Xmonad works to write a simple Managehook action. Toby -- Dr T. S. Cubitt Mathematics and Quantum Information group Department of Mathematics Complutense University Madrid, Spain email: tsc25@cantab.net web: www.dr-qubit.org

On Sat, Feb 11, 2012 at 17:46, Toby Cubitt
I'm trying to write a Managehook that only shifts a window to workspace if that workspace is empty. But I'm quickly realising I don't have a good enough grasp of Xmonad types, and Haskell monads in general, to get it to work.
So far, the closest I think I've got is the following:
myManageHook = [ className =? "mutt" --> doShiftEmpty "email" ] where doShiftEmpty t = when (isEmpty t) (doShift t) isEmpty t = do wsl <- gets $ W.workspaces . windowset let mws = find (\ws -> W.tag ws == t) wsl return $ maybe True (isNothing . W.stack) mws
which throws a type error:
"Couldn't match expected type `Bool' with actual type `m0 Bool'
The problem here is that your function wants to execute in the X monad, but is actually running in the Query monad because it's in a ManageHook. The fix is to wrap it in liftX: className =? "mutt" --> liftX (doShiftEmpty "email") By the way, did you really mean className there? mutt is terminal based; className will therefore always be the terminal program you're using, and will start with an uppercase letter. Assuming you're using -name or similar to set the instance name for the terminal to "mutt", you probably want appName instead. -- brandon s allbery allbery.b@gmail.com wandering unix systems administrator (available) (412) 475-9364 vm/sms

On Sat, Feb 11, 2012 at 18:11, Brandon Allbery
className =? "mutt" --> liftX (doShiftEmpty "email")
Oops, slightly wrong; liftX will propagate the result back, which in this case is () which is not compatible with (Endo WindowSet) as expected by ManageHook. The correct fix is
appName =? "mutt" --> liftX (doShiftEmpty "email") >> idHook
which discards the () and substitutes an appropriate do-nothing Endo WindowSet. -- brandon s allbery allbery.b@gmail.com wandering unix systems administrator (available) (412) 475-9364 vm/sms

On Sat, Feb 11, 2012 at 06:20:44PM -0500, Brandon Allbery wrote:
On Sat, Feb 11, 2012 at 18:11, Brandon Allbery
wrote: className =? "mutt" --> liftX (doShiftEmpty "email")
Oops, slightly wrong; liftX will propagate the result back, which in this case is () which is not compatible with (Endo WindowSet) as expected by ManageHook. The correct fix is
appName =? "mutt" --> liftX (doShiftEmpty "email") >> idHook
which discards the () and substitutes an appropriate do-nothing Endo WindowSet.
-- brandon s allbery allbery.b@gmail.com wandering unix systems administrator (available) (412) 475-9364 vm/sms
_______________________________________________ xmonad mailing list xmonad@haskell.org http://www.haskell.org/mailman/listinfo/xmonad
-- Dr T. S. Cubitt Mathematics and Quantum Information group Department of Mathematics Complutense University Madrid, Spain email: tsc25@cantab.net web: www.dr-qubit.org

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi, On 02/11/2012 11:46 PM, Toby Cubitt wrote:
I'm trying to write a Managehook that only shifts a window to workspace if that workspace is empty. But I'm quickly realising I don't have a good enough grasp of Xmonad types, and Haskell monads in general, to get it to work.
So far, the closest I think I've got is the following:
myManageHook = [ className =? "mutt" --> doShiftEmpty "email" ] where doShiftEmpty t = when (isEmpty t) (doShift t) isEmpty t = do wsl <- gets $ W.workspaces . windowset let mws = find (\ws -> W.tag ws == t) wsl return $ maybe True (isNothing . W.stack) mws
which throws a type error:
"Couldn't match expected type `Bool' with actual type `m0 Bool' In the return type of a call of `isEmpty'" you probally want to try "whenX" then.
You can easily the test if a workspace is empty like this: MonadState XState m => WorkspaceId -> m Bool \t -> gets $ elem t . map S.tag . filter (isNothing . S.stack) . S.workspaces . windowset
I think I vaguely understand the problem, namely that "when" expects a Bool as its first argument, whereas the "return" in isEmpty returns a Bool wrapped inside a monad. But removing the "return" just throws a more confusing type error. Clearly, I'm way out of my depth here, and am doing little better than cargo cult programming.
Can someone who understands these things properly explain where I'm going wrong here?
More generally, is there a tutorial explaining the Xmonad types and data structures, and how they go together to make up Xmoand? I've been working XMonad is documented on xmonad.org as annotated source files. There are also some documents describing how to write extensions/hooks. I don't have the links at hand atm, but I think you'll find them without problems. Aaaaaaaaand.. there's always the source. :)
through some basic Haskell tutorials, but there's still quite a step from understanding a little Haskell, to understanding enough of how Xmonad works to write a simple Managehook action. For learning Haskell from my experiences I can recommend "Real World Haskell", reading xmonad's source, and hacking on xmonad..
Best wishes, Jochen Sorry for the noise. As it happened many times before I replied only the sender and forgot to cc the list. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iEYEARECAAYFAk829wYACgkQtVwvsA+W4CCP3gCfUJcRNVOPBh2bHr29Xy5R6QEs qYoAn1xNCeDycdzVn+owJbtpHk/vTh6s =uo3c -----END PGP SIGNATURE-----
participants (3)
-
Brandon Allbery
-
Jochen Keil
-
Toby Cubitt