Haskell:处理 IO 内部故障的常见模式 :: IO(任一字符串整数)



试图理解用于处理IO内部可能故障的模式。如果它只是像下面这样的一个case,它可能可以接受,但如果嵌套一堆嵌套IO (Either String Int)继续下去,是否有一种通用模式来处理此类类型。例如,如果functionDoSomething中的b再次成为一种(Either a b),并且获得成功的价值并再次使用它将是另一种case。我可以使用高阶函数吗?我还不熟悉单子变压器,不确定它们是否可以用来处理这个特定的单子堆栈。如果它们可以在这里使用,有没有办法在不使用它们的情况下做到这一点。

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变压器并不是你想要解决的第一个概念。然而,在这种情况下,它是要使用的模式

可以这么说,Monads 通常使您能够"编织进进出函子"。如果你只有Either,你可以使用带有do符号的Either值从值中提取Right值,同时短路Left情况。

但是,在这种情况下,您有一堆monads:EitherIO内部。因此,当您尝试使用do表示法时,您处于IO上下文中,这意味着,如 OP 所示,您使用<-箭头从函数中"拉出"的值仍然是Either值。

Monad 转换器使您能够将 monad 堆栈(例如,在本例中EitherIO中的值(视为Monad实例,以便您可以(例如(在堆栈上使用do符号。

虽然您希望Eithermonad 变压器被称为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

最新更新