顺序monad中优雅的haskell case /错误处理 [英] Elegant haskell case/error handling in sequential monads

查看:181
本文介绍了顺序monad中优雅的haskell case /错误处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因为我过分简化了我的其他问题,所以我想给出一个更清晰的例子。



我该如何处理需要以顺序方式检查certian条件而不嵌套多个case的情况?使用顺序方式,我的意思是得到一个值(例如从标准输入),检查这个值的一定条件,并取决于获得另一个值的结果等。



例子:

  sequential:IO字符串
sequen = do
a < - getLine
案例a
hi - >做
putStrLn你好!
b < - getLine

的情况b你好吗? - >做
putStrLn很好,谢谢
返回nice talk
_ - >返回错误2
_ - >返回错误1

我知道有更好的方法来编写这样的聊天机器人,它应该只是展示问题的顺序性质。正如你所看到的,对于每一个嵌套的情况,代码也会进一步缩进。



有没有办法更好地构造这样的代码?我正在考虑在一个地方处理错误,并描述成功路径,而不是将错误处理分发给它。

当然。这正是 EitherT 所做的。你可以从 Control.Monad.Trans.Either 中找到或T 包。

  import Control.Monad.Trans.Class 
import Control.Monad.Trans.Either

main = do
e< - runEitherT $ do
a< - lift getLine
a
hi - >解除$ putStrLn你好!
_ - >留下1
b < - lift getLine

的情况b你好吗? - >举起$ putStrLn很好,谢谢!
_ - > left 2
returnnice conversation
case e of
Left n - > putStrLn $Error - Code:++ show n
Right str - > putStrLn $Success - String:++ str

EitherT 在遇到 left 语句时会放弃当前的代码块,而人们通常会使用它来表示错误情况。



内部块的类型是 EitherT Int IO String 。当你 runEitherT 时,你得到 IO(Int Int String) Left 类型对应于失败时出现 left Right value表示它已成功到达块的结尾。


Because I oversimplified in my other question before, I would like to give a more clear example here.

How can I handle situations where I have to check for certian conditions in a sequential way without nesting multiple cases? With "sequential way" I mean getting a value (e.g. from stdin), checking this value for a certain condition and depending on the outcome getting another value and so on.

Example:

sequen :: IO String
sequen = do
  a <- getLine
  case a of
    "hi" -> do
      putStrLn "hello!"
      b <- getLine
      case b of
        "how are you?" -> do
          putStrLn "fine, thanks"
          return "nice conversation"
        _ -> return "error 2"
    _ -> return "error 1"

I know that there are better ways to write such a chat bot, it should just demonstrate the sequential nature of the problem. As you can see, with every nested case, the code also gets indented deeper.

Is there a way to better structure such code? I'm thinking of handling the "errors" on one place and describing the "success-path" without the error handling distributed all over it.

解决方案

Of course. This is precisely what EitherT was made for. You can get it from Control.Monad.Trans.Either in the eitherT package.

import Control.Monad.Trans.Class
import Control.Monad.Trans.Either

main = do
    e <- runEitherT $ do
        a <- lift getLine
        case a of
            "hi" -> lift $ putStrLn "hello!"
            _    -> left 1
        b <- lift getLine
        case b of
            "how are you?" -> lift $ putStrLn "fine, thanks!"
            _              -> left 2
        return "nice conversation"
    case e of
        Left  n   -> putStrLn $ "Error - Code: " ++ show n
        Right str -> putStrLn $ "Success - String: " ++ str

EitherT aborts the current code block whenever it encounters a left statement, and people typically use this to indicate error conditions.

The inner block's type is EitherT Int IO String. When you runEitherT it, you get IO (Either Int String). The Left type corresponds to the case where it failed with a left and the Right value means it successfully reached the end of the block.

这篇关于顺序monad中优雅的haskell case /错误处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆