Haskell:处理结果来自计算

时间:2016-08-15 18:14:12

标签: haskell nested parsec either

我重新访问了Haskell,并构建了一个玩具编程语言解析器/解释器。使用Parsec进行lexing和解析以及单独的解释器。我正在解决一些问题,将解析器的结果提供给我的解释器,并处理解释器和解析器的潜在错误。我最终得到这样的东西:

main = do
  fname <- getArgs
  input <- readFile (head fname)
  case lparse (head fname) input of
    Left msg -> putStrLn $ show msg
    Right p -> case intrp p of
      Left msg -> putStrLn $ show msg
      Right r -> putStrLn $ show r

这个看起来很漂亮。我的问题是,lparse返回Either ParseError [(String, Stmt)]itrp返回类型Either ItrpError Stmt,因此我很难从Right结果中获取ParseError结果解析器解析器,同时保释并打印可能的IntrpErrormain = do fname <- getArgs input <- readFile (head fname) let prog = lparse (head fname) input (putStrLn . show) (intrp <$> prog)

最接近我想要的是这样的

Lefts

但这不会令人惊讶地产生嵌套的Either,也不会打印得很漂亮。

那么有没有任何好的Haskell思想方法来做这个线程从一个计算到另一个计算并以一种很好的方式处理错误(lparse)而没有嵌套案例?

修改

添加itrplparse :: Text.Parsec.Pos.SourceName -> String -> Either Text.Parsec.Error.ParseError [([Char], Stmt)] intrp :: [([Char], Stmt)] -> Either IntrpError Stmt

的类型
service = discovery.build('gmail', 'v1', http=http)

2 个答案:

答案 0 :(得分:4)

虽然不完美,但我会创建一个辅助函数,用于将Show中任何Either错误的错误嵌入到MonadError中:

{-# LANGUAGE FlexibleContexts #-}
import Control.Monad.Except

strErr :: (MonadError String m, Show e) => Either e a -> m a
strErr = either (throwError . show) return

然后,如果您的计算可能会因错误而失败,例如

someFn :: ExceptT String IO ()
someFn = strErr (Left 42)

您可以将其运行(将错误打印到 stdout

main :: IO ()
main = runExceptT someFn >>= either putStrLn return

在你的情况下,它就像是

main = either putStrLn return <=< runExceptT $ do
  fname <- liftIO getArgs
  input <- liftIO $ readFile (head fname)
  prog <- strErr $ lparse (head fname) input
  r <- strErr $ interp prog
  print r

答案 1 :(得分:2)

好吧,如果你想连接成功的计算,你总是可以使用>>=来做到这一点。例如在你的情况下:

lparse (head fname) input >>= intrp

如果你想打印出你的错误信息,你可以使用带有两个处理函数的either类,一个用于Left a的情况(你的情况是错误的)和另一个对于Right b(在您的情况下是成功的事情)。一个例子:

either (putStrLn . show) (putStrLn . show) (lparse (head fname) input >>= intrp)

如果您的链条中的任何内容失败(您的monadic链的任何步骤变为Left a)它就会停止,并且可以在上述情况下打印出错误消息。