Для уни у меня есть этот проект, где мне нужно запрограммировать простую игру в Haskell. Прямо сейчас я столкнулся со следующей проблемой:
instance Renderable Player where
render (MkPlayer pos rad bults _) = do playerpic <- displayimg pos rad "./images/player.bmp"
bulletpics <- ...
return $ pictures (playerpic:bulletpics)
в ...
мне нужна функция f :: [Bullet] -> IO [Picture]
где функция, создающая изображение для объекта пули:
render :: Bullet -> IO Picture
есть ли способ создать нужную мне функцию. Я играл на бумаге с монадами и функторами, но не могу найти способ сделать это. Любая помощь вообще с этим очень ценится!!
Для этого можно использовать mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b):
instance Renderable Player where
render (MkPlayer pos rad bults _) = do
playerpic <- displayimg pos rad "./images/player.bmp"
bulletpics <- mapM render bults
return $ pictures (playerpic:bulletpics)
Вы можете использовать traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)
. В вашем коде это выглядит так:
instance Renderable Player where
render (MkPlayer pos rad bults _) = do playerpic <- displayimg pos rad "./images/player.bmp"
bulletpics <- traverse render bults
return $ pictures (playerpic:bulletpics)
Предоставленные решения для обозначения do
вполне нормальны и просты для понимания новичком. Но с большим опытом вы также можете рассмотреть возможность использования аппликативного стиля, чтобы было понятнее (как читателю, так и компилятору), что обработка игрока и пуль независимы:
instance Renderable Player where
render (MkPlayer pos rad bults _) = liftA2 go
(displayimg pos rad "./images/player.bmp")
(traverse render bults)
where go playerpic bulletpics = pictures $ playerpic : bulletpics