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
在我们的例子中,我们认识到 a
和 b
都是 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
产生。
我正在使用 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
在我们的例子中,我们认识到 a
和 b
都是 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
产生。