简体   繁体   中英

XMonad: How to write functions involving the `Query` datatype?

Problem

I have a feeling that the reason for this question is going to ultimately come down to me just being new at/not understanding Haskell, so I'll try to be as detailed as I can with my description, to make it somewhat generic.

I am using a custom XMonad config as my window manager, defined in a file xmonad.hs .

The XMonad manageHook is what I use to handle when certain applications need to open in a certain type of window or on a certain workspace, etc. https://hackage.haskell.org/package/xmonad-0.17.0/docs/XMonad-ManageHook.html

Currently, a bunch of lines in my manageHook in xmonad.hs look like this:

className =? "xxxx" --> doSomething

Here is my current understanding of the line above:

These expressions involve the value of className , defined in XMonad.Hooks.ManageHook , which is of the Query type ( Query [Char] , to be more specific). https://hackage.haskell.org/package/xmonad-0.17.0/docs/XMonad-ManageHook.html

Query is defined in XMonad.Core . https://hackage.haskell.org/package/xmonad-0.17.0/docs/XMonad-Core.html#t:Query

=? takes the Query [Char] on the left and the [Char] literal on the right and returns a value of type Query Bool ; the value will be True if the [Char] s are equal and False otherwise (I think?)

--> takes the Query Bool on the left and an action on the right and executes the action if the value of the Query Bool is True .

https://hackage.haskell.org/package/xmonad-0.17.0/docs/XMonad-ManageHook.html

However, this is only useful to me when I know the exact class name of an application I want to apply a rule to, which is not always the case. So, I took a look at xmonad-contrib to get some ideas as to what other functions I could define.

In XMonad.Hooks.ManageHelpers ( https://hackage.haskell.org/package/xmonad-contrib-0.17.0/docs/XMonad-Hooks-ManageHelpers.html ), there is ^? , which would be used like below:

className ^? "xxxx" --> doSomething

From my understanding, ^? takes the Query [Char] on the left and the [Char] literal on the right and returns a value type of Query Bool ; the value will be True if the [Char] on the left isPrefixOf the [Char] on the right and False otherwise (I think?)

What I would like to create is a new function that is similar, but reversed. Something like,

"xxxx" ?^ className --> doSomething

where ?^ takes the [Char] literal on the left and the Query [Char] on the right and returns a value of type Query Bool ; the value should be True if the [Char] on the left isPrefixOf the [Char] on the right and False otherwise. (In other words, I want to define a new function that checks if some string literal is a prefix of the class name, rather than checking if the class name is a prefix of some string literal.)

Initially, I thought this should be easy, but looking at the source code for ^?, I realized there must be something I am fundamentally missing about my understanding of Haskell.

Here is the definition of ^? :

(^?) :: (Eq a, Functor m) => m [a] -> [a] -> m Bool
q ^? x = fmap (`isPrefixOf` x) q

https://hackage.haskell.org/package/xmonad-contrib-0.17.0/docs/src/XMonad.Hooks.ManageHelpers.html#%5E%3F

What I do not understand is how I would write a function that is a reversed version of this. This definitely won't work:

(?^) :: (Eq a, Functor m) => [a] -> m [a] -> m Bool
x ?^ q = fmap (`isPrefixOf` q) q

yet I do not understand why. What property does Query have that (Query [a]) isPrefixOf ([a]) is acceptable, but not ([a]) isPrefixOf (Query [a]) ?

Furthermore, how can I go about defining a function with the desired behavior? I am still pretty new to Haskell, so I do not know where to start.

Solution

I was closer than I thought. See the answer for more details, but the solution was just to fix my syntax for the invocation of isPrefixOf (oops):

x ?^ q = fmap (x `isPrefixOf`) q

You gotta switch the arguments to isPrefixOf !

x ?^ q = fmap (x `isPrefixOf`) q

Other spellings are possible, such as this version that doesn't use the infix form of isPrefixOf :

x ^? q = isPrefixOf x <$> q

( (<$>) is another name for fmap .)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM