XMonad:如何编写涉及“查询”数据类型的函数?

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

问题

我觉得这个问题的原因最终会归结为我是新手 at/not 理解 Haskell,所以我会尽可能详细加上我的描述,让它有点通用。

我正在使用自定义 XMonad 配置作为我的 window 管理器,在文件 xmonad.hs.

中定义

XMonad manageHook 是我用来处理某些应用程序需要在特定类型的 window 或特定工作区等中打开时使用的工具。 https://hackage.haskell.org/package/xmonad-0.17.0/docs/XMonad-ManageHook.html

目前,我的 manageHookxmonad.hs 中的一堆行如下所示:

className =? "xxxx" --> doSomething

这是我目前对上面这行的理解:

这些表达式涉及 className 的值,定义在 XMonad.Hooks.ManageHook 中,属于 Query 类型(Query [Char],更具体地说)。 https://hackage.haskell.org/package/xmonad-0.17.0/docs/XMonad-ManageHook.html

QueryXMonad.Core 中定义。 https://hackage.haskell.org/package/xmonad-0.17.0/docs/XMonad-Core.html#t:Query

=? 接受左边的 Query [Char] 和右边的 [Char] 文字,returns 一个 Query Bool 类型的值;如果 [Char] 相等,则值为 True,否则为 False(我认为?)

--> 接受左边的 Query Bool 和右边的一个动作,如果 Query Bool 的值为 True.[=69,则执行该动作=]

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

但是,这仅在我知道要对其应用规则的应用程序的确切 class 名称时才有用,但情况并非总是如此。因此,我查看了 xmonad-contrib 以获得一些关于我可以定义哪些其他功能的想法。

XMonad.Hooks.ManageHelpershttps://hackage.haskell.org/package/xmonad-contrib-0.17.0/docs/XMonad-Hooks-ManageHelpers.html)中,有^?,用法如下:

className ^? "xxxx" --> doSomething

根据我的理解,^? 接受左侧的 Query [Char] 和右侧的 [Char] 文字以及 returns Query Bool 的值类型;如果左侧 [Char] isPrefixOf 右侧 [Char] 则值为 True,否则为 False(我认为?)

我想创建的是一个类似但相反的新功能。像,

"xxxx" ?^ className --> doSomething

其中 ?^ 接受左侧的 [Char] 文字和右侧的 Query [Char] 以及 returns 类型 Query Bool 的值;如果左侧的 [Char] isPrefixOf 右侧的 [Char],则该值应为 True,否则为 False。 (换句话说,我想定义一个新函数来检查某个字符串文字是否是 class 名称的前缀,而不是检查 class 名称是否是某个字符串文字的前缀。)

最初,我认为这应该很容易,但是查看 ^? 的源代码后,我意识到我对 Haskell.[=69 的理解一定有一些根本上缺失的东西=]

这里是^?的定义:

(^?) :: (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

我不明白的是我将如何编写一个与此相反的函数。这肯定不行:

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

但我不明白为什么。什么属性Query有什么(Query [a]) isPrefixOf ([a])可以接受,而([a]) isPrefixOf (Query [a])不行?

此外,我该如何着手定义具有所需行为的函数?我对 Haskell 还是很陌生,所以我不知道从哪里开始。

解决方案

我比我想象的要近。有关更多详细信息,请参阅答案,但解决方案只是修复我调用 isPrefixOf 的语法(oops):

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

您必须将参数切换为 isPrefixOf

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

其他拼写也是可能的,比如这个不使用 isPrefixOf 的中缀形式的版本:

x ^? q = isPrefixOf x <$> q

((<$>)fmap 的别称。)