顺序monad中优雅的haskell case /错误处理 [英] Elegant haskell case/error handling in sequential monads
问题描述
因为我过分简化了我的其他问题,所以我想给出一个更清晰的例子。
我该如何处理需要以顺序方式检查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屋!