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 ab)
并且在成功时获取值并再次用它做某事将是另一个这样的<代码>案例代码>.是否有我可以使用的高阶函数?我对 monad 转换器还不满意,不确定它们是否可以用来处理这个特定的 monad 堆栈.如果它们可以在这里使用,有没有不使用它们的方法.
Trying to understand the pattern used to deal with possible failures inside IO
. If its just one case
s like below, its probably acceptable, but if the nesting goes on for a bunch of nested IO (Either String Int)
s is there a common pattern to handle such types. For instance, if b
in functionDoSomething
is again a (Either a b)
and fetching value on success and doing something with it again will be another such case
. Is there a higher order function that I can use? I'm not comfortable with monad transformers yet, not sure if they can be used to deal with this specific monad stack. If they can be used here, is there a way to do it without using them.
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 转换器并不是您想要解决的第一个概念.在这种情况下,是,但是,要使用的模式.
I understand that you're new to Haskell, and that monad transformers aren't the first concept you'd want to grapple with. In a situation like this, it is, however, the pattern to use.
一般来说,Monads 可以让你织入和织出函子",可以这么说.如果您只有 Either
,您可以使用带有 do
符号的 Either
值来提取 Right
值值,同时将 Left
情况短路.
Monads in general enable you to 'weave in and out of functors', so to speak. Had you only had Either
, you could have used the Either
values with do
notation to pull the Right
values out of the values, while short-circuiting the Left
cases.
然而,在这种情况下,您有一个堆栈"的 monad:Either
位于 IO
内.因此,当您尝试使用 do
表示法时,您处于 IO
上下文中,这意味着,正如 OP 所示,您从' 使用 <-
箭头的函数仍然是 Either
值.
In this case, however, you have a 'stack' of monads: Either
inside of IO
. Thus, when you attempt to use do
notation, you're in the IO
context, and that means that, as the OP illustrates, the values that you 'pull out of' the functions, using the <-
arrow, are still Either
values.
Monad 转换器使您能够将 monad 堆栈(例如,在本例中 IO
中的 Either
值)视为 Monad
实例,因此例如,您可以在堆栈上使用 do
符号.
Monad transformers enable you to treat stacks of monads (like, in this case Either
values inside of IO
) as Monad
instances, so that you can, e.g., use do
notation on the stack.
虽然您希望 Either
monad 转换器被称为 EitherT
,但由于各种原因,它被称为 ExceptT
.您可以像这样稍微简化 OP 代码:
While you'd expect the Either
monad transformer to be called EitherT
, it is, for various reasons, called ExceptT
. You could simplify the OP code slightly like this:
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
.
Here, created
is an Int
value, which can then be passed to functionDoSomething
.
这篇关于Haskell:处理 IO 内部故障的常见模式 :: IO (Either String Int)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!