Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell/XMonad:围绕Monad的包装器,它还跟踪数据_Haskell_Wrapper_Monads_Xmonad - Fatal编程技术网

Haskell/XMonad:围绕Monad的包装器,它还跟踪数据

Haskell/XMonad:围绕Monad的包装器,它还跟踪数据,haskell,wrapper,monads,xmonad,Haskell,Wrapper,Monads,Xmonad,这是一个后续行动。我要求对X t操作“需要清理”(完成后松开按钮和/或键盘)的情况进行类型检查。他的回答是一个一元包装器NeedsCleanup,我当前的实现是这样的: {-# LANGUAGE GeneralizedNewtypeDeriving #-} newtype NeedsCleanup m t = NeedsCleanup { -- | Escape hatch from the NeedsCleanup Monad; -- returns

这是一个后续行动。我要求对
X t
操作“需要清理”(完成后松开按钮和/或键盘)的情况进行类型检查。他的回答是一个一元包装器
NeedsCleanup
,我当前的实现是这样的:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

newtype NeedsCleanup m t = 
  NeedsCleanup
    {
      -- | Escape hatch from the NeedsCleanup Monad;
      --   returns the original action.
      original_action :: m t
    }
  deriving (Functor, Applicative, Monad)

-- | executes unclean_action and cleans up afterwards.
--   (cleanedUp action) is a normal X() action
cleanedUp :: NeedsCleanup X t -> X t
cleanedUp unclean_action = do
  result <- original_action unclean_action
  doCleanup
  return result
两个
cleanUpdatea
可以组合在一起,大致形成一个联合(“之后,您必须对这两个操作进行清理”)

例如,如果:

action1::NeedsCleanup X()
dta1::cleanupda

action2::NeedsCleanup X()
dta2::cleanupda

然后,
action1>>action2
应该与
CombineCleanUpdatea dta1 dta2
相关联(大致为“您需要为两者清理的内容”)

最后,函数
cleanedUp::NeedsCleanup X t->X t
应该执行底层的
X t
操作,并获取该操作的
cleanupda
(以查看需要清理的内容)

是否可以使用一元包装器以这种方式跟踪数据


更新:


最后,我使用了与Ilmo Euro的答案类似的东西,只是为CleanUpdatea定义了一个幺半群结构,而不是使用列表幺半群。类似于:

import Control.Monad.Writer.Lazy (WriterT(..), runWriterT, tell, MonadWriter(..))
import Control.Monad.Trans.Class (MonadTrans(..))
import Data.Monoid (Monoid(..))

initialCleanupData =
  CleanupData
    {
        keyboard_needs_cleanup = False
      , buttons_needing_cleanup = Set.empty

      -- initial values for other fields
    }

instance Monoid CleanupData where
  mempty = initialCleanupData
  mappend = combineCleanupData

newtype NeedsCleanup m t = 
  NeedsCleanup
    {
      to_writable :: WriterT CleanupData m t
    } deriving (MonadTrans, Monad, Applicative, Functor, MonadIO, MonadWriter CleanupData)

cleanup :: NeedsCleanup X t -> X t
cleanup action = do
  (ret_val, cleanup_data) <- runWriterT (to_writable action)

  -- clean up based on cleanup_data
  --   ...

  return ret_val 
needsCleanup_GrabButton
  :: MonadIO m => Display -> Window -> Button -> NeedsCleanup m ()
needsCleanup_GrabButton dply window button = do
    liftIO $ grabButton dply button anyModifier window True buttonReleaseMask grabModeAsync grabModeAsync none none

    tell cleanup_data
  where
    -- the stuff we need to clean up from this
    -- particular action
    cleanup_data = initialCleanupData
      {
          buttons_needing_cleanup = Set.singleton button
      }

例如,您可以使用
Writer
monad:

import Control.Monad.Writer

data DirtyThing = Keyboard | Mouse
newtype Dirty m a = Dirty { unDirty :: WriterT [DirtyThing] m a }

doFoo :: Dirty IO ()
doFoo = -- doing something dirty

cleanup :: Dirty m a -> m a
cleanup action = do
    (val, dirtyThings) <- runWriterT (unDirty action)
    -- cleanup dirtyThings
    return val
import Control.Monad.Writer
数据脏东西=键盘|鼠标
newtype Dirty ma=Dirty{underty::WriterT[DirtyThing]ma}
doFoo::脏IO()
doFoo=--做一些肮脏的事情
清理::脏m a->m a
清理动作=do

(val,dirtyThings)我最终使用了类似的东西,只是为cleanUpdatea定义了一个幺半群结构(参见OP)。您能检查我是否正确定义了
需要清理抓取按钮吗?(我想,但我不确定,这就是我应该如何使用
tell
)@SPACINGISE它看起来不错,虽然有点不习惯。我会像
liftIO$。。。;告诉你你的数据;return()
好的,我想我明白了,谢谢;必须使
NeedsCleanup
成为
MonadWriter cleanupda
的一个实例。如果我错了,请纠正我,但我不认为最后一个
return()
是必要的?
needsCleanup_GrabButton
  :: MonadIO m => Display -> Window -> Button -> NeedsCleanup m ()
needsCleanup_GrabButton dply window button = do
    liftIO $ grabButton dply button anyModifier window True buttonReleaseMask grabModeAsync grabModeAsync none none

    tell cleanup_data
  where
    -- the stuff we need to clean up from this
    -- particular action
    cleanup_data = initialCleanupData
      {
          buttons_needing_cleanup = Set.singleton button
      }
import Control.Monad.Writer

data DirtyThing = Keyboard | Mouse
newtype Dirty m a = Dirty { unDirty :: WriterT [DirtyThing] m a }

doFoo :: Dirty IO ()
doFoo = -- doing something dirty

cleanup :: Dirty m a -> m a
cleanup action = do
    (val, dirtyThings) <- runWriterT (unDirty action)
    -- cleanup dirtyThings
    return val