IO (возможно изображение) -> изображение

Я создаю игру с Gloss. У меня есть эта функция:

block :: IO (Maybe Picture)
block = loadJuicyPNG "block.png"

Как мне взять этот IO (возможно изображение) и превратить его в изображение?

2 ответа

Решение

Вам необходимо связать значение. Это делается либо с помощью функции связывания (>>=)или do-notation:

main :: IO ()
main = do
    pic <- block
    case pic of
        Just p -> ...   -- loading succeeded, p is a Picture
        Nothing -> ...  -- loading failed

Это Maybe Picture потому что загрузка может произойти сбой, и вы должны как-то обработать этот возможный сбой.

Это в основном тот же ответ, что и у Бартека, но с использованием другого подхода.

Допустим, у вас есть функция foo :: Picture -> Picture преобразовывает картину в некотором роде. Это ожидает Picture в качестве аргумента, но все, что у вас есть, это block :: IO (Maybe Picture); там может быть или не быть картина, похороненная там, но это все, что у вас есть.

Для начала предположим, что у вас есть какая-то функция foo' :: Maybe Picture -> Maybe Picture, Это определение просто:

foo' :: Maybe Picture -> Maybe Picture
foo' = fmap foo

На самом деле так просто, что ты никогда не пишешь этого; где бы вы ни использовали foo'Вы просто используете fmap foo непосредственно. Как вы помните, эта функция выполняет возврат Nothing если получится Nothing, и вернуться Just (foo x) если он получает какое-то значение Just x,

Теперь, учитывая, что у вас есть foo'как применить его к значению, скрытому в IO тип? Для этого мы будем использовать Monad например IO, который предоставляет нам две функции (типы здесь специализируются на IO):

return :: a -> IO a
(>>=) :: IO a -> (a -> IO b) -> IO b

В нашем случае мы признаем, что оба a а также b являются Maybe Picture, Если foo' :: Maybe Picture -> Maybe Picture, затем return . foo' :: Maybe Picture -> IO (Maybe Picture), Это означает, что мы можем, наконец, "применить" foo к нашей картине:

> :t block  >>= return . (fmap foo)
block  >>= return . (fmap foo) :: IO (Maybe Picture)

Но мы на самом деле не применяем foo сами. То, что мы действительно делаем, это лифтинг foo в контекст, где однажды block выполняется, foo' можно вызвать на что угодно block производит.

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