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
目前,我的 manageHook
在 xmonad.hs
中的一堆行如下所示:
className =? "xxxx" --> doSomething
这是我目前对上面这行的理解:
这些表达式涉及 className
的值,定义在 XMonad.Hooks.ManageHook
中,属于 Query
类型(Query [Char]
,更具体地说)。
https://hackage.haskell.org/package/xmonad-0.17.0/docs/XMonad-ManageHook.html
Query
在 XMonad.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.ManageHelpers
(https://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
我不明白的是我将如何编写一个与此相反的函数。这肯定不行:
(?^) :: (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
的别称。)
问题
我觉得这个问题的原因最终会归结为我是新手 at/not 理解 Haskell,所以我会尽可能详细加上我的描述,让它有点通用。
我正在使用自定义 XMonad 配置作为我的 window 管理器,在文件 xmonad.hs
.
XMonad manageHook
是我用来处理某些应用程序需要在特定类型的 window 或特定工作区等中打开时使用的工具。
https://hackage.haskell.org/package/xmonad-0.17.0/docs/XMonad-ManageHook.html
目前,我的 manageHook
在 xmonad.hs
中的一堆行如下所示:
className =? "xxxx" --> doSomething
这是我目前对上面这行的理解:
这些表达式涉及 className
的值,定义在 XMonad.Hooks.ManageHook
中,属于 Query
类型(Query [Char]
,更具体地说)。
https://hackage.haskell.org/package/xmonad-0.17.0/docs/XMonad-ManageHook.html
Query
在 XMonad.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.ManageHelpers
(https://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
我不明白的是我将如何编写一个与此相反的函数。这肯定不行:
(?^) :: (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
的别称。)