如何从 Maybe 中提取 IO () 并执行它?
How can I extract an IO () from Maybe and execute this?
我有这个代码:
trick = Just (putStrLn "Hello?")
我想将这个 IO ()
解包到 Maybe 上下文中并调用它。
main = do foo <- trick
foo
但是,这会引发错误:
Couldn't match type ‘IO’ with ‘Maybe’
Expected type: Maybe ()
Actual type: IO ()
我该如何解决这个问题?
开始时最简单的解决方案可能是认识到您可以通过模式匹配根据 Maybe (IO ())
的值来决定要做什么。
maybeDoIO :: Maybe (IO ()) -> IO ()
maybeDoIO (Just io) = io
maybeDoIO Nothing = return ()
你必须考虑 Nothing
,基本上:
main = maybe (putStrLn "Nothing") id foo
您要找的函数是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 ()
你的 main
函数的问题是你在同一个 do
块中混合了两个不同的单子。
foo <- trick
动作对 Maybe
monad 来说是 "relative",但之后的 foo
动作是 IO
动作。 >>=
的类型是:
Monad m => m a -> (a -> m b) -> m b
但在您的情况下,您需要以下类型的内容:
Maybe a -> (a -> IO b) -> IO b
有两个不同的单子。
如果要执行 IO
操作,那么 main
的类型必须 是 IO a
类型,因此 do
符号必须引用 IO
而不是 Maybe
。这意味着您 不能 使用 <-
来提取操作,但您必须使用其他东西。例如 Data.Maybe.fromMaybe
:
import Data.Maybe
main = do fromMaybe (return ()) trick
我有这个代码:
trick = Just (putStrLn "Hello?")
我想将这个 IO ()
解包到 Maybe 上下文中并调用它。
main = do foo <- trick
foo
但是,这会引发错误:
Couldn't match type ‘IO’ with ‘Maybe’
Expected type: Maybe ()
Actual type: IO ()
我该如何解决这个问题?
开始时最简单的解决方案可能是认识到您可以通过模式匹配根据 Maybe (IO ())
的值来决定要做什么。
maybeDoIO :: Maybe (IO ()) -> IO ()
maybeDoIO (Just io) = io
maybeDoIO Nothing = return ()
你必须考虑 Nothing
,基本上:
main = maybe (putStrLn "Nothing") id foo
您要找的函数是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 ()
你的 main
函数的问题是你在同一个 do
块中混合了两个不同的单子。
foo <- trick
动作对 Maybe
monad 来说是 "relative",但之后的 foo
动作是 IO
动作。 >>=
的类型是:
Monad m => m a -> (a -> m b) -> m b
但在您的情况下,您需要以下类型的内容:
Maybe a -> (a -> IO b) -> IO b
有两个不同的单子。
如果要执行 IO
操作,那么 main
的类型必须 是 IO a
类型,因此 do
符号必须引用 IO
而不是 Maybe
。这意味着您 不能 使用 <-
来提取操作,但您必须使用其他东西。例如 Data.Maybe.fromMaybe
:
import Data.Maybe
main = do fromMaybe (return ()) trick