module Rahm.Desktop.Layout.ReinterpretMessage where import Data.Proxy (Proxy (..)) import XMonad (SomeMessage, X) import XMonad.Layout.LayoutModifier (LayoutModifier (..)) -- This is a type class that defines how to reinterpret a message. One can think -- of this as a kind of type-level function. It lets one associate a function -- (reinterpretMessage) with a type construct, which for the case below is a -- Symbol. -- -- It would be nice to attach this function to the LayoutModifier directly as a -- value, however LayoutModifiers must be Show-able and Read-able and functions -- are not. However encoding in the typesystem itsef which function is to be -- called is the best alternative I have. class DoReinterpret (k :: t) where reinterpretMessage :: Proxy k -> SomeMessage -> X (Maybe SomeMessage) -- Data construct for association a DoReinterpret function with a concrete -- construct that can be used in the LayoutModifier instance. -- -- It would be nice to have ReinterpretMessage hold the function as a value -- rather than delegate to this kind-instance, however, it won't work because -- LayoutModifiers have to be Read-able and Show-able, and functions are neither -- of those, so a value-level function may not be a member of a LayoutModifier, -- thus I have to settle for delegating to a hard-coded instance using -- type-classes. data ReinterpretMessage k a = ReinterpretMessage deriving (Show, Read) -- Instance for ReinterpretMessage as a Layout modifier. instance (DoReinterpret k) => LayoutModifier (ReinterpretMessage k) a where handleMessOrMaybeModifyIt self message = do -- Delegates to the reinterpretMessage function associated with the -- type-variable k. newMessage <- reinterpretMessage (ofProxy self) message case newMessage of Just m -> return $ Just $ Right m Nothing -> return $ Just $ Left self where -- ofProxy just provides reifies the phantom type k so the type system can -- figure out what instance to go to. ofProxy :: ReinterpretMessage k a -> Proxy k ofProxy _ = Proxy