7

如何发出多个调用SDL.pollEvent :: IO Event直到输出SDL.NoEvent并将所有结果收集到一个列表中?

在命令式术语中是这样的:

events = []
event = SDL.pollEvent
while ( event != SDL.NoEvent ) {
        events.add( event )
        event = SDL.pollEvent
}
4

5 回答 5

4

你可以使用类似的东西:

takeWhileM :: (a -> Bool) -> IO a -> IO [a]
takeWhileM p act = do
  x <- 行动
  如果像素
    然后做
      xs <- takeWhileM p act
      返回(x:xs)
    别的
      返回 []

代替:

做
  xs <- takeWhileM p act
  返回(x:xs)

您还可以使用:

liftM (x:) (takeWhileM p act)产生:

takeWhileM :: (a -> Bool) -> IO a -> IO [a]
takeWhileM p act = do
  x <- 行动
  如果像素
    然后 liftM (x:) (takeWhileM p act)
    否则返回 []

然后你可以使用:takeWhileM (/=SDL.NoEvent) SDL.pollEvent

于 2010-05-16T15:30:49.807 回答
4

James Cook 非常好心地用这个函数扩展了monad-loop :

unfoldWhileM  :: Monad  m => (a -> Bool) -> m a -> m [a]

与 SDL 一起使用:

events <- unfoldWhileM (/= SDL.NoEvent) SDL.pollEvent
于 2010-07-15T12:37:37.903 回答
2

您可以使用一元列表:

import Control.Monad.ListT (ListT)
import Control.Monad.Trans.Class (lift) -- transformers, not mtl
import Data.List.Class (takeWhile, repeat, toList)
import Prelude hiding (takeWhile, repeat)

getEvents :: IO [Event]
getEvents = 
    toList . takeWhile (/= NoEvent) $ do
        repeat ()
        lift pollEvent :: ListT IO Event

ListT来自hackage的“列表”包。

于 2010-05-16T14:50:00.843 回答
1

将这些存根用于EventpollEvent

data Event = NoEvent | SomeEvent
  deriving (Show,Eq)

instance Random Event where
  randomIO = randomRIO (0,1) >>= return . ([NoEvent,SomeEvent] !!)

pollEvent :: IO Event
pollEvent = randomIO

和一个从较早的答案借用和改编的组合器,它在谓词第一次失败时停止评估

spanM :: (Monad m) => (a -> Bool) -> m a -> m [a]
spanM p a = do
  x <- a
  if p x then do xs <- spanM p a
                 return (x:xs)
         else return [x]

允许这个 ghci 会话,例如:

*Main> spanM (/= NoEvent) pollEvent
[一些事件,一些事件,无事件]
于 2010-05-17T03:05:31.983 回答
0

我最终在一个来自hackage的实际SDL游戏中偶然发现了这个代码片段

getEvents :: IO Event -> [Event] -> IO [Event]
getEvents pEvent es = do
  e <- pEvent
  let hasEvent = e /= NoEvent
  if hasEvent
   then getEvents pEvent (e:es)
   else return (reverse es)

谢谢你的回答顺便说一句!

于 2010-05-17T00:32:07.010 回答