'要么'用IO传播()

时间:2015-07-13 19:00:46

标签: haskell

我正在学习Haskell,并且度过了愉快的时光。我特别喜欢的一件事是使用monad错误类型在fmap或>> =中传播场景后面的错误条件。例如,在此代码中,我使用hoauth2进行身份验证的连接。它使用Either ...

定义OAuth2Result
type OAuth2Result a = Either ByteString a  -- from OAuth2

getEntries :: Manager -> AccessToken -> IO(OAuth2Result [Entry])
  -- code omitted

filterResults :: [Entry] -> OAuth2Result [Entry]
filterResults = return $ filter hasUrl 

printEntries :: [Entry] -> IO()   -- What type can I use here?
printEntries Left l  =  -- code omitted
printEntries Right r =  -- code omitted

main = do
    entriesResult <- getEntries mgr token  -- This is an OAuth2Result
    let filtered = entriesResult >>= filterResults

    printEntries filtered

我遇到的问题是函数有像printEntries这样的IO。在这种情况下,我必须显式模式匹配才能进行错误处理。我肯定希望能够以某种方式隐藏它,就像我使用filterResults调用一样。

我该怎么做?

谢谢!

1 个答案:

答案 0 :(得分:1)

以下是如何使用runEitherT进行操作,这需要一些提升和提升才能使类型正确:

import Control.Monad
import Control.Monad.Trans
import Control.Error

import Data.List (isInfixOf)

type Entry = String
type Result a = Either String a

sampleEntries = [ "good 1", "good 2", "good 3", "bad 4", "good 5", "bad 6", "good 7" ]

getEntries :: Int -> IO (Result [Entry])
getEntries n = if n >= 0 && n <= length sampleEntries
                 then return $ Right $ take n sampleEntries
                 else return $ Left $ "invalid n: " ++ show n

filterEntries :: [Entry] -> Result [Entry]
filterEntries ents = if all isGood ents
                       then Right $ ents
                       else Left "found a bad entry"
  where isGood str = isInfixOf "good" str

printEntries :: [Entry] -> IO ()
printEntries ents = forM_ (zip [1..] ents) $ \(i,e) -> print (i,e)

doit n = do
  ents <- (lift $ getEntries n) >>= hoistEither
  filtered <- hoistEither $ filterEntries ents
  lift $ printEntries filtered

main n = do result <- runEitherT $ doit n
            case result of
              Left e -> putStrLn $ "Error: " ++ e
              Right _ -> putStrLn $ "no errors"

请注意以下行为:

  • main 100失败,因为getEntries返回错误
  • main 4失败,因为filterEntries返回错误
  • main 3成功