Haskell:处理 IO 内部故障的常见模式 :: IO (Either String Int) [英] Haskell: Common pattern to deal with Failure inside IO :: IO (Either String Int)

查看:73
本文介绍了Haskell:处理 IO 内部故障的常见模式 :: IO (Either String Int)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

试图理解用于处理 IO 中可能出现的故障的模式.如果它只是一个像下面这样的 cases,它可能是可以接受的,但是如果嵌套继续一堆嵌套的 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 cases 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆