如何发出多个调用SDL.pollEvent :: IO Event
直到输出SDL.NoEvent
并将所有结果收集到一个列表中?
在命令式术语中是这样的:
events = []
event = SDL.pollEvent
while ( event != SDL.NoEvent ) {
events.add( event )
event = SDL.pollEvent
}
如何发出多个调用SDL.pollEvent :: IO Event
直到输出SDL.NoEvent
并将所有结果收集到一个列表中?
在命令式术语中是这样的:
events = []
event = SDL.pollEvent
while ( event != SDL.NoEvent ) {
events.add( event )
event = SDL.pollEvent
}
你可以使用类似的东西:
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
James Cook 非常好心地用这个函数扩展了monad-loop :
unfoldWhileM :: Monad m => (a -> Bool) -> m a -> m [a]
与 SDL 一起使用:
events <- unfoldWhileM (/= SDL.NoEvent) SDL.pollEvent
您可以使用一元列表:
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的“列表”包。
将这些存根用于Event
和pollEvent
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 [一些事件,一些事件,无事件]
我最终在一个来自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)
谢谢你的回答顺便说一句!