转换a(IO b)到IO(ab)

und*_*all 2 io haskell types

再一次,通过一些糟糕的,糟糕的编程,我已经设法让自己陷入了类型的糟糕局面.

有没有办法转换Either a (IO b)IO (Either a b)?我知道,让自己陷入这种状况不是很好的编程,所以我也愿意接受如何避免这种情况的建议.

ram*_*ion 5

当然!

convert :: Either a (IO b) -> IO (Either a b)
convert = either (return . Left) (fmap Right)
Run Code Online (Sandbox Code Playgroud)

现在,如果你想转换IO (Either a b)Either a (IO b),你会遇到麻烦,但你没有,所以你没事.

让我们看看它是如何convert工作的:

  • either :: (a -> c) -> (b -> c) -> Either a b -> c,所以它需要照顾模式对我们的匹配,搞清楚我们是否有一个aIO b你的情况.
  • 如果我们有a,我们只需将其转换为IO (Either a b).构造函数Left :: a -> Either a b做的第一部分,IO是一个单子,所以我们可以使用returnEither a b -> IO (Either a b).
  • 如果我们有IO b,我们需要将其转换为IO (Either a b).我们可以用符号来做到这一点:

    given iob = do
      b <- iob
      return . Right $ b
    
    Run Code Online (Sandbox Code Playgroud)

    使用return . Rightas b -> IO (Either a b).但这正是mapM :: Monad m => (a -> b) -> m a -> m bMonads的情况:given iob = mapM Right iob.mapM但是,大多数人并没有使用,因为它只是fmapMonads 的专业化,所以我们将使用fmap:given iob = fmap Right iob,或者,pointfree : given = fmap Right.

  • 这里``convert``实际上是``sequenceA``的特例,从``Data.Traversable``导出. (12认同)
  • @scrambledeggs你应该把它变成答案,即使这个答案已经被接受了. (2认同)