从EventM中删除当前侦听器

时间:2018-03-02 20:52:45

标签: javascript haskell ghcjs ghcjs-dom

假设我想使用ghcjs-dom创建一个响应点击的事件监听器,然后自行删除。

我有

addListener :: (IsEventTarget t, IsEvent e)
            => t -> EventName t e -> SaferEventListener t e -> Bool -> IO ()
removeListener :: (IsEventTarget t, IsEvent e)
            => t -> EventName t e -> SaferEventListener t e -> Bool -> IO ()

添加和删除,以及

newListener :: (IsEvent e) => EventM t e () -> IO (SaferEventListener t e)

EventM构建侦听器。如何从SaferEventListener中访问EventM(我将稍后构建),以便在事件发生时将其删除?

在JavaScript中,您使用命名函数表达式作为回调addEventListener,然后在回调中将removeEventListener应用于该名称。但这里似乎没有任何类比。或者我错过了什么?

1 个答案:

答案 0 :(得分:2)

使用fixIO

fixIO $ \rec -> newListener _eventm

使用_eventm填充EventM,您将能够访问最终将通过名称rec创建的事件监听器。 rec将是newListener电话的结果,但可以"使用"}在执行之前。我说'#34;用过,"因为试图用seq强制它或任何更强的东西会导致无限循环,但你应该做你正在做的事情。

fixIOfix

的概括
-- the essence of recursion
fix :: (a -> a) -> a
fix f = let x = f x in x
-- equivalent but less performant and less relevant
fix f = f (fix f)

-- if you have used JS's "named anonymous functions"
-- this will seem very familiar
(fix (\fact n ->
  if n <= 1 then 1 else n * fact (n - 1)
)) 3 = 6
-- JS:
-- (function fact(n) {
--   if(n <= 1) { return 1; } else { return n * fact(n - 1); }
-- })(3) === 6

-- but this has more power
repeat = fix . (:)
repeat 1 = fix (1:) = 
   let x = 1:x in x = 1:fix (1:) = [1,1,1,1,1,1,1,1,1,1,1,1,1,1...]

fix id = let x = id x in x = let x = x in x = _|_ -- oops!

fixIO :: (a -> IO a) -> IO a
fixIO f = _ -- horrendous, unsafe code

fixIO (\xs -> return $ 1:xs) = return [1,1,1,1,1,1,1,1,1,1...]

fixIO return = fixIO (return . id) = return $ fix id = return _|_ -- oops!

fix的想法是在实际创建函数之前使函数的最终结果可用。
fixIO的想法是在实际创建之前使IO函数的最终结果可用,同时还执行一些IO操作。此外,fixIO只执行一次的这些操作,这就是fix的第一个定义(仅调用f一次)与第二个定义相关的原因

反过来,

fixIOmfix :: MonadFix m => (a -> m a) -> m a的特化,其中MonadFix是monad的类(包括IOmfix = fixIO)承认这种打结语义。 GHC支持&#34;递归do&#34;任何MonadFix的表示法:

{-# LANGUAGE RecursiveDo #-}
someCode = mdo ...
               listener <- newListener _eventm -- can access listener in definition
               ...
-- or
someCode = do ...
              rec listener <- newListener _eventm
              ...