Haskell: IO :: IO (Either String Int) 内部处理失败的通用模式
Haskell: Common pattern to deal with Failure inside IO :: IO (Either String Int)
试图了解用于处理内部可能故障的模式 IO
。如果它只是一个像下面这样的 case
s,它可能是可以接受的,但是如果嵌套继续进行一堆嵌套的 IO (Either String Int)
s 是否有处理此类类型的通用模式。例如,如果 functionDoSomething
中的 b
又是一个 (Either a b)
并且在成功时获取值并再次用它做某事将是另一个这样的 case
。我可以使用更高阶的函数吗?我对 monad 转换器还不太满意,不确定它们是否可以用来处理这个特定的 monad 堆栈。如果它们可以在这里使用,有没有不用它们的方法。
import Control.Monad
functionCreate :: Int -> IO (Either String Int)
functionDoSomething :: Int -> IO b
functionUse :: IO ()
functionUse = do
created <- functionCreate 10
case created of
(Right v) -> void $ functionDoSomething v
_ -> return ()
我知道您是 Haskell 的新手,并且 monad 转换器不是您想要解决的第一个概念。在这种情况下,它 是 ,但是,要使用的模式。
一般来说,Monad 可以让你 'weave in and out of functors',可以这么说。如果您只有 Either
,您可以使用带有 do
符号的 Either
值将 Right
值从值中拉出,同时将 [=15] 短路=] 例。
然而,在这种情况下,您有一个 'stack' 个单子:Either
在 IO
内。因此,当您尝试使用 do
表示法时,您处于 IO
上下文中,这意味着,正如 OP 所示,您 'pull out of' 函数的值,使用<-
箭头,仍然是 Either
值。
Monad 转换器使您能够将 monad 堆栈(例如,在本例中 IO
内的 Either
值)视为 Monad
个实例,这样您就可以,例如,使用do
堆栈上的符号。
虽然您希望 Either
monad 转换器被称为 EitherT
,但由于各种原因,它被称为 ExceptT
。您可以像这样稍微简化 OP 代码:
import Control.Monad (void)
import Control.Monad.IO.Class (liftIO)
import Control.Monad.Trans.Except
functionUse :: IO (Either String ())
functionUse = runExceptT $ do
created <- ExceptT $ functionCreate 10
liftIO $ void $ functionDoSomething created
这里,created
是一个Int
值,然后可以传递给functionDoSomething
。
试图了解用于处理内部可能故障的模式 IO
。如果它只是一个像下面这样的 case
s,它可能是可以接受的,但是如果嵌套继续进行一堆嵌套的 IO (Either String Int)
s 是否有处理此类类型的通用模式。例如,如果 functionDoSomething
中的 b
又是一个 (Either a b)
并且在成功时获取值并再次用它做某事将是另一个这样的 case
。我可以使用更高阶的函数吗?我对 monad 转换器还不太满意,不确定它们是否可以用来处理这个特定的 monad 堆栈。如果它们可以在这里使用,有没有不用它们的方法。
import Control.Monad
functionCreate :: Int -> IO (Either String Int)
functionDoSomething :: Int -> IO b
functionUse :: IO ()
functionUse = do
created <- functionCreate 10
case created of
(Right v) -> void $ functionDoSomething v
_ -> return ()
我知道您是 Haskell 的新手,并且 monad 转换器不是您想要解决的第一个概念。在这种情况下,它 是 ,但是,要使用的模式。
一般来说,Monad 可以让你 'weave in and out of functors',可以这么说。如果您只有 Either
,您可以使用带有 do
符号的 Either
值将 Right
值从值中拉出,同时将 [=15] 短路=] 例。
然而,在这种情况下,您有一个 'stack' 个单子:Either
在 IO
内。因此,当您尝试使用 do
表示法时,您处于 IO
上下文中,这意味着,正如 OP 所示,您 'pull out of' 函数的值,使用<-
箭头,仍然是 Either
值。
Monad 转换器使您能够将 monad 堆栈(例如,在本例中 IO
内的 Either
值)视为 Monad
个实例,这样您就可以,例如,使用do
堆栈上的符号。
虽然您希望 Either
monad 转换器被称为 EitherT
,但由于各种原因,它被称为 ExceptT
。您可以像这样稍微简化 OP 代码:
import Control.Monad (void)
import Control.Monad.IO.Class (liftIO)
import Control.Monad.Trans.Except
functionUse :: IO (Either String ())
functionUse = runExceptT $ do
created <- ExceptT $ functionCreate 10
liftIO $ void $ functionDoSomething created
这里,created
是一个Int
值,然后可以传递给functionDoSomething
。