如何从Maybe中提取IO()并执行此操作?

时间:2015-04-08 14:00:44

标签: haskell monads

我有这段代码:

trick = Just (putStrLn "Hello?")

我想将这个IO ()从Maybe上下文中解开并调用它。

main = do foo <- trick
          foo

但是,这会引发错误:

Couldn't match type ‘IO’ with ‘Maybe’
Expected type: Maybe ()
  Actual type: IO ()

我该如何解决这个问题?

4 个答案:

答案 0 :(得分:6)

您正在寻找的功能是Data.Foldable.sequence_

>>> Data.Foldable.sequence_ (Just (putStrLn "Hello?"))
Hello?
>>>

如果您的MaybeNothing,则不会执行任何操作:

>>> Data.Foldable.sequence_ Nothing
>>>

这是有效的,因为Data.Foldable.sequence_的类型是:

Data.Foldable.sequence_
    :: (Foldable t, Monad m) => t (m a) -> m ()

...如果您将t专门设定为Maybem专注于IO,则可获得:

Data.Foldable.sequence_ :: Maybe (IO a) -> IO ()

Maybe的特定背景下,它等同于:

sequence_ (Just io) = do
    _ <- io
    return ()
sequence   Nothing  = return ()

答案 1 :(得分:3)

最简单的解决方案可能是要意识到您可以根据Maybe (IO ())通过模式匹配的值来决定做什么。

maybeDoIO :: Maybe (IO ()) -> IO ()
maybeDoIO (Just io) = io
maybeDoIO Nothing   = return ()

答案 2 :(得分:1)

您必须考虑Nothing,基本上:

main = maybe (putStrLn "Nothing") id foo

答案 3 :(得分:1)

main函数的问题在于您在同一个do块中混合了两个不同的monad。

foo <- trick行动是&#34;亲属&#34;到Maybe monad,但之后的foo操作是IO操作。 >>=的类型为:

Monad m => m a -> (a -> m b) -> m b

但在你的情况下,你需要类型的东西:

Maybe a -> (a -> IO b) -> IO b

有两个不同的monad。

如果您要执行IO操作,则main 的类型必须属于IO a类型,因此do符号必须请参阅IO而不是Maybe。这意味着您无法使用<-来提取操作,但您必须使用其他内容。例如Data.Maybe.fromMaybe

import Data.Maybe

main = do fromMaybe (return ()) trick