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
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
CodePudding user response:
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
.)