Reputation: 4219
I have a function that looks like:
sinkFocus :: StackSet i l a s sd -> Maybe (StackSet i l a s sd)
sinkFocus = (fmap . flip sink) <*> peek
However I would like an X ()
so that I can use it. For example additionalKeys
uses an X ()
.
The documentation says that X
is a IO
with some state and reader transformers, so I am under the impression that the StackSet
is contained within the state of X
. So in theory it should be possible to modify the relevant part of the state. However the state accessible is XState
not the StackState
I want, so I need to be able to turn my function on StackState
to one on XState
.
This would be easy enough if I had a function of the type
(StackSet i l a s sd -> StackSet i l a s sd) -> X ()
However after digging around in the documentation I haven't been able to piece together a way to do this yet. Is there a way to take a function on StackSet
and make an X ()
that performs that function?
Upvotes: 1
Views: 337
Reputation: 4219
The X
monad has an instance of MonadState
instance MonadState XState X
So we can use modify
as
modify :: (XState -> XState) -> X ()
So we need to turn out function to one on XState
s. And if we look at the definition
XState
windowset :: !WindowSet
mapped :: !(Set Window)
waitingUnmap :: !(Map Window Int)
dragging :: !(Maybe (Position -> Position -> X (), X ()))
numberlockMask :: !KeyMask
extensibleState :: !(Map String (Either String StateExtension))
we will see WindowSet
which is a type alias for a particular StackState
. So you can turn a function from StackState
s into one on XState
s like so:
overWindowSet :: (WindowSet -> WindowSet) -> XState -> XState
overWindowSet f xState = xState { windowset = f (windowset xState) }
This can be combined with modify
to make the complete function you would like:
modify . overWindowSet
Upvotes: 2