3

我编写了以下代码来替换我得到的错误消息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对于使用现有原语或一般的单子原语来做到这一点的方法有什么建议吗?

4

1 回答 1

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
    
于 2013-09-14T23:07:22.723 回答