1

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

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

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

4

2 回答 2

6

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

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

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

于 2018-12-07T15:15:38.677 回答
1

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

假设您有一个foo :: Picture -> Picture以某种方式转换图片的功能。它期望 aPicture作为参数,但您所拥有的只是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实例化 for IO,它为我们提供了两个函数(这里专门用于 的类型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)。这意味着我们最终可以“应用”foo到我们的图片上:

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

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

于 2018-12-07T20:40:43.467 回答