我正在用 Gloss 创建一个游戏。我有这个功能:
block :: IO (Maybe Picture)
block = loadJuicyPNG "block.png"
如何获取此 IO(可能是图片)并将其转换为图片?
我正在用 Gloss 创建一个游戏。我有这个功能:
block :: IO (Maybe Picture)
block = loadJuicyPNG "block.png"
如何获取此 IO(可能是图片)并将其转换为图片?
您需要绑定该值。这可以通过 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
因为加载可能会失败,您必须以某种方式处理可能的失败。
这与 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
在我们的例子中,我们认识到两者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
产生的东西上调用。