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<-行為
  pxの場合
    その後、
      xs <-takeWhileM p act
      return(x:xs)
    そうしないと
      戻る []

それ以外の:

行う
  xs <-takeWhileM p act
  return(x:xs)

次のものも使用できます。

liftM (x:) (takeWhileM p act)降伏:

takeWhileM ::(a-> Bool)-> IO a-> IO [a]
takeWhileM p act = do
  x<-行為
  pxの場合
    次にliftM(x :)(takeWhileM p act)
    それ以外の場合は[]を返します

次に、次を使用できます。takeWhileM (/=SDL.NoEvent) SDL.pollEvent

于 2010-05-16T15:30:49.807 に答える
4

James Cook は親切にもモナドループをこの関数で拡張してくれました:

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ハックの「リスト」パッケージから。

于 2010-05-16T14:50:00.843 に答える
1

これらのスタブを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

そして、述語が最初に失敗したときに評価を停止する、以前の answerから借用して適合させたコンビネータ

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

私は最終的に、ハックからの実際の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 に答える