IO(可能是图片)-> 图片

IO (Maybe Picture) -> Picture

我正在使用 Gloss 创建游戏。 我有这个功能:

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

如何将此 IO(可能是图片)转换为图片?

您需要绑定该值。这可以通过绑定函数 (>>=)do-notation:

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

这是一个 Maybe Picture 因为加载可能会失败,您必须以某种方式处理这种可能的失败。

这与 Bartek 的答案基本相同,但使用了不同的方法。

假设您有一个函数 foo :: Picture -> Picture 可以以某种方式转换图片。它需要一个 Picture 作为参数,但你所拥有的只是 block :: IO (Maybe Picture);里面可能有也可能没有照片,但你只有这些了。

首先,假设您有一些功能 foo' :: Maybe Picture -> Maybe Picture。它的定义很简单:

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

如此简单,事实上,您从未真正写过它;无论你在哪里使用 foo',你都可以直接使用 fmap foo。你会记得,这个函数的作用是 return Nothing 如果它得到 Nothing,如果它得到一些值 return Just (foo x) Just x .

现在,假设您有 foo',您如何将它应用到埋藏在 IO 类型中的值?为此,我们将使用为 IO 实例化的 Monad,它为我们提供了两个函数(此处专门针对 IO 的类型):

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

在我们的例子中,我们认识到 ab 都是 Maybe Picture。如果 foo' :: Maybe Picture -> Maybe Picture,则 return . foo' :: Maybe Picture -> IO (Maybe Picture)。这意味着我们终于可以"apply" foo 到我们的图片了:

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

但我们自己并没有真正应用 foo。我们真正做的是将foo提升到一个上下文中,一旦block被执行,foo'可以在任何block 产生。