EitherT和错误的习惯用法

时间:2013-09-14 22:51:40

标签: haskell

我编写了以下代码来替换我从readFile获得的错误消息:

module Main where

import Control.Error
import qualified Data.ByteString.Lazy as BSL

replaceLeftT :: Monad m => String -> EitherT String m a -> EitherT String m a
replaceLeftT message e = EitherT $ do
  unwrapped <- runEitherT e
  let x = case unwrapped of
            Left _ -> Left message
            y      -> y
  return x

main :: IO ()
main = runScript $ do
  contents <- replaceLeftT "Could not read file" $
                scriptIO $ BSL.readFile "somefile"
  scriptIO $ putStrLn "Won't get here"

我觉得很笨,就像我错过了一个基本概念。可能是因为我主要通过反复试验推导出这个功能......

对于使用现有Control.Error原语或一般monad原语的方法有任何建议吗?

1 个答案:

答案 0 :(得分:4)

有不同的方法可以实现这一目标:

  1. 使用hushTnoteT

    您可以首先将其丢弃(hushT),然后添加新的错误消息(noteT)来覆盖错误消息。

    replaceLeftT :: Monad m => String -> EitherT String m a -> EitherT String m a
    replaceLeftT message = noteT message . hushT
    -- Same as: replaceLeftT message e = noteT message $ hushT e
    
  2. 使用fmapLT

    另一种可能性是使用fmapLT修改Left中的邮件。为了实现replaceLeftT,我们总是返回相同的新值,忽略旧的值:

    replaceLeftT :: Monad m => String -> EitherT String m a -> EitherT String m a
    replaceLeftT = fmapLT . const
    -- Same as: replaceLeftT message e = fmapLT (const message) e