52700.fb2 Учебник по Haskell - читать онлайн бесплатно полную версию книги . Страница 336

Учебник по Haskell - читать онлайн бесплатно полную версию книги . Страница 336

:: Sensor H.Shape -> IxMap Obj -> IO (Maybe Event)

getClick

:: Sensor H.Position -> IO (Maybe Event)

Далее мы не будем каждый раз выписывать новые неопределённые функции, мы будем просто оставлять

объявления типов без определений. Итак мы написали одну функцию, и получили ещё четыре новых.

Мы сделаем предположение о том, что сначала мы реагируем на непрерывные события, а затем на дис-

кретные. Причём к запросам на реакции могут привести только дискретные события:

updatePure :: Sense -> [Event] -> Pure -> (Pure, [Query])

updatePure s evts = updateEvents evts . updateSenses s

-- в Pure.hs

updateSenses :: Sense -> Pure -> Pure

updateEvents :: [Event] -> Pure -> (Pure, [Query])

В функции react мы предполагаем, что реакции мира на события независимы друг от друга. foldQuery~–

функция свёртки для типа Query.

import Control.Monad

...

react :: [Query] -> Dirty -> IO Dirty

react = foldr (<=< ) return

. fmap (foldQuery removeBall heroVelocity makeBall)

-- в Dirty.hs

removeBall

:: Ball

-> Dirty -> IO Dirty

heroVelocity

:: H.Velocity

-> Dirty -> IO Dirty

makeBall

:: Freq

-> Dirty -> IO Dirty

Обратите внимание на то, как мы воспользовались функциями foldr, return и <=< для того чтобы нани-

зать друг на друга функции типа Dirty -> IO Dirty. Напомню, что функция <=< ~– это аналог композиции

для монадных функций.

Обновление модели:

updateDirty :: Dirty -> IO Dirty

updateDirty = stepDirty dt

-- в Dirty.hs

Детализируем функции обновления состояния игры | 303

stepDirty :: H.Time -> Dirty -> IO Dirty

-- в Inits.hs

dt :: H.Time

dt = 0.5

Функции рисования поместим в отдельный модуль Graphics. hs

-- переместим из Loop.hs в World.hs

drawWorld :: World -> IO ()

drawWorld = draw . picture . worldPure

-- в Graphics.hs

draw :: Picture -> IO ()

-- в Pure.hs

picture

:: Pure -> Picture