Проблемы с объектами ввода-вывода Haskell

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

есть ли способ создать нужную мне функцию. Я играл на бумаге с монадами и функторами, но не могу найти способ сделать это. Любая помощь вообще с этим очень ценится!!

Что такое компоненты React? Введение в компоненты | Типы компонентов
Что такое компоненты React? Введение в компоненты | Типы компонентов
Компонент - это независимый, многократно используемый фрагмент кода, который делит пользовательский интерфейс на более мелкие части. Например, если мы...
2
1
152
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Для этого можно использовать 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

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