我有这段代码:
trick = Just (putStrLn "Hello?")
我想将这个IO ()
从Maybe上下文中解开并调用它。
main = do foo <- trick
foo
但是,这会引发错误:
Couldn't match type ‘IO’ with ‘Maybe’
Expected type: Maybe ()
Actual type: IO ()
我该如何解决这个问题?
答案 0 :(得分:6)
您正在寻找的功能是Data.Foldable.sequence_
:
>>> Data.Foldable.sequence_ (Just (putStrLn "Hello?"))
Hello?
>>>
如果您的Maybe
为Nothing
,则不会执行任何操作:
>>> Data.Foldable.sequence_ Nothing
>>>
这是有效的,因为Data.Foldable.sequence_
的类型是:
Data.Foldable.sequence_
:: (Foldable t, Monad m) => t (m a) -> m ()
...如果您将t
专门设定为Maybe
,m
专注于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