首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >xmonad‘asks <-问题(工作区)。(配置)‘魔术--我如何解析它?

xmonad‘asks <-问题(工作区)。(配置)‘魔术--我如何解析它?
EN

Stack Overflow用户
提问于 2020-04-02 21:22:39
回答 3查看 352关注 0票数 1

我正在从XMonad.Actions.WindowMenu中插入xmonad-contrib模块,试图使其可配置。

我很难理解以下几点:

原码中有一个类似于:

代码语言:javascript
复制
windowMenu :: X ()
windowMenu = withFocused $ \w -> do
    tags <- asks (workspaces . config)
    -- ...

了解那里发生了什么最好的方法是什么?换句话说,在什么环境下评估整个tags <- asks (workspaces . config)

我提出这个问题的原因是,当我试图在不同的功能中重构它时:

代码语言:javascript
复制
defaultActs :: [(String, X ())]
defaultActs = do
    tags <- asks (workspaces . config)
    [ ("A: " ++ tag, return ()) | tag <- tags]

它因一个错误而爆炸:

代码语言:javascript
复制
    • No instance for (MonadReader XConf [])
        arising from a use of ‘asks’
    • In a stmt of a 'do' block: tags <- asks (workspaces . 
      In the expression:
        do tags <- asks (workspaces . config)
           [("A: " ++ tag, return ()) | tag <- tags]
      In an equation for ‘defaultActs’:
          defaultActs
            = do tags <- asks (workspaces . config)
                 [("A: " ++ tag, return ()) | tag <- tags]

编辑后添加:

我理解这一声明的类型:

代码语言:javascript
复制
ghci> :t asks (workspaces . config)
asks (workspaces . config) :: MonadReader XConf m => m [String]
ghci> :t withFocused
withFocused :: (Window -> X ()) -> X ()

但它破裂的原因仍然是个谜。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-04-03 20:22:29

最简单的方法是让windowMenudefaultActions都在X monad中操作,后者已经有了适当的MonadReader实例。所以:

代码语言:javascript
复制
defaultActions :: X [(String, X ())]
defaultActions = do
    tags <- asks (workspaces . config)
    return ([ ("Cancel menu", return ())
            , ("Close"      , kill)
            , ("Maximize"   , withFocused $ \w -> sendMessage $ maximizeRestore w)
            , ("Minimize"   , withFocused $ \w -> minimizeWindow w)
            ] ++
            [ ("Move to " ++ tag, windows $ W.shift tag) | tag <- tags ])

windowMenu :: X ()
windowMenu = withFocused $ \w -> do
    acts <- defaultActions
    Rectangle x y wh ht <- getSize w
    Rectangle sx sy swh sht <- gets $ screenRect . W.screenDetail . W.current . windowset
    let originFractX = (fi x - fi sx + fi wh / 2) / fi swh
        originFractY = (fi y - fi sy + fi ht / 2) / fi sht
        gsConfig = (buildDefaultGSConfig colorizer)
                    { gs_originFractX = originFractX
                    , gs_originFractY = originFractY }
    runSelectedAction gsConfig acts

另一个答案中的恶作剧使windowMenu'成为参数化的高阶函数.如果您确实希望创建一个windowMenu',使您能够对操作列表进行参数化,请直接这样做:

代码语言:javascript
复制
windowMenu' :: [(String, X ())] -> X ()
windowMenu' acts = withFocused $ \w -> do
    Rectangle x y wh ht <- getSize w
    Rectangle sx sy swh sht <- gets $ screenRect . W.screenDetail . W.current . windowset
    let originFractX = (fi x - fi sx + fi wh / 2) / fi swh
        originFractY = (fi y - fi sy + fi ht / 2) / fi sht
        gsConfig = (buildDefaultGSConfig colorizer)
                    { gs_originFractX = originFractX
                    , gs_originFractY = originFractY }
    runSelectedAction gsConfig acts

在这种情况下,您可以运行defaultActions并使用(>>=) (或更多的do符号)将其结果传递给windowMenu'

代码语言:javascript
复制
windowMenu :: X ()
windowMenu = defaultActions >>= windowMenu'
-- OR
windowMenu = do
    acts <- defaultActions
    windowMenu' acts
票数 2
EN

Stack Overflow用户

发布于 2020-04-03 14:16:48

好吧,多亏了杜普拉德的回答,我才弄明白了:

代码语言:javascript
复制
defaultActions :: XConf -> [(String, X ())]
defaultActions = do
    tags <- asks (workspaces . config)
    return ([ ("Cancel menu", return ())
            , ("Close"      , kill)
            , ("Maximize"   , withFocused $ \w -> sendMessage $ maximizeRestore w)
            , ("Minimize"   , withFocused $ \w -> minimizeWindow w)
            ] ++
            [ ("Move to " ++ tag, windows $ W.shift tag) | tag <- tags ])

windowMenu' :: (XConf -> [(String, X ())]) -> X ()
windowMenu' actions = withFocused $ \w -> do
    acts <- asks actions
    Rectangle x y wh ht <- getSize w
    Rectangle sx sy swh sht <- gets $ screenRect . W.screenDetail . W.current . windowset
    let originFractX = (fi x - fi sx + fi wh / 2) / fi swh
        originFractY = (fi y - fi sy + fi ht / 2) / fi sht
        gsConfig = (buildDefaultGSConfig colorizer)
                    { gs_originFractX = originFractX
                    , gs_originFractY = originFractY }
    runSelectedAction gsConfig acts

-- now it composes well, and I can pass in my own `actions` to `windowMenu`
windowMenu = windowMenu' defaultActions

顺便说一句,我无法使它作为X [String]类型工作(不知道为什么),但上面的解决方案似乎运行得很好。也许这不是最好的(不确定),但它带我去我想去的地方。

票数 1
EN

Stack Overflow用户

发布于 2020-04-02 21:27:53

不看任何文档,我们就知道了这一点:这是在withFocused所需要的任何类型的do-表示法的上下文中。它显然以一个函数作为参数,该函数必须返回某种类型的一元值。这个do表示法块的值必须具有相同的类型。它当然没有[(String, X ())]类型。(好吧,好吧,它可以,因为[a]是一个单曲,但这种类型似乎不太可能是withFocused期望的结果)。

您可以通过查看文档来找出它的类型。

代码语言:javascript
复制
withFocused :: (Window -> X ()) -> X ()

因为我们的do-表示法在第一个参数lambda的返回值中,所以它必须有一种X ()类型。因此,

代码语言:javascript
复制
asks (workspaces . config) :: X t

对于一些t,我们也可以通过查找workspaces的类型来知道。<-以通常的方式将t值绑定到名称tags

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61001342

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档