Вопрос

Как я могу выдать несколько звонков на SDL.pollEvent :: IO Event пока вывод не будет SDL.NoEvent и соберите все результаты в список?

В императивных условиях что-то вроде этого:

events = []
event = SDL.pollEvent
while ( event != SDL.NoEvent ) {
        events.add( event )
        event = SDL.pollEvent
}
Это было полезно?

Решение

Джеймс Кук был так добр, чтобы продлить монад-петляс этой функцией:

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

Используется с SDL:

events <- unfoldWhileM (/= SDL.NoEvent) SDL.pollEvent

Другие советы

Вы могли бы использовать что-то вроде:

Takewhemilem :: (a -> bool) -> IO A -> IO [A] ACT WHITHECHILEM P = DO X <- ACT Если PX Тогда сделайте XS <- RecainWickilem P ATT RETURN (X: XS) еще возврата [

Вместо:

DO XS <- RecakhemeM P ATT RETTAL (X: XS)

Вы также можете использовать:

liftM (x:) (takeWhileM p act) Урожайность:

Takewhemilem :: (a -> bool) -> IO A -> IO [A] ACT WHITHILEM P = DO X <- ACT, если PX, затем SiteM (X :) (ACTHICHILEM P AT))

Тогда вы можете использовать: takeWhileM (/=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 Из пакета «Список» на Gackage.

Используя эти заглушки для 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, например:

* Главная> Spanm (/ = NoEvent) Pollevent [Someevent, Someevent, NoEvent

В конечном итоге я в конечном итоге наткнулся на этот фрагмент кода в реальной SDL Game от Hackage

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)

Спасибо за ваши ответы, кстати!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top