gpt4 book ai didi

haskell - 如何从这段代码中删除 `case of`?

转载 作者:行者123 更新时间:2023-12-02 17:22:20 26 4
gpt4 key购买 nike

如何重写以下代码,使其:

  1. 使用较少的字符
  2. 最多包含一个案例......
-- parseSQL :: String -> Either ParseError SQL
-- evalSQL :: SQL -> IO (Either EvalError Table)
-- prettyPrintTable :: Table -> IO ()
-- ParseError, EvalError and Table are instances of Show

evalAndPrint :: String -> IO ()
evalAndPrint x =
case parseSQL x of
(Left parseErr) ->
print parseErr
(Right sql) -> do
result <- evalSQL sql
case result of
(Left err) ->
print err
(Right table) -> do
prettyPrintTable table
putStrLn $ "(" ++ show (length table) ++ " lines)\n"

最佳答案

目前,我们假设您已经概括了 parseSQLevalSQL具有这些类型的函数(稍后我们将看到如何将您的专用实现转换为通用实现,即使您无权访问其源代码):

parseSQL :: MonadError ParseError m => String -> m SQL
evalSQL :: (MonadError EvalError m, MonadIO m) => SQL -> m Table

然后我们可以这样写:

-- if we were really doing this the mtl way, we'd introduce a new
-- type class for changing error types instead of specializing to
-- ExceptT, but that's another answer
evalAndThrow :: String -> ExceptT String IO ()
evalAndThrow s = do
sql <- withExceptT show (parseSQL s)
table <- withExceptT show (evalSQL sql)
liftIO $ prettyPrintTable table
liftIO . putStrLn $ "(" ++ show (length table) ++ " lines)\n"

顶层函数可以是这样的

evalAndPrint s = do
v <- runExceptT (evalAndThrow s)
case v of
Left err -> putStrLn err
Right _ -> return ()

这里有一些将现有函数转换为 mtl 风格的多态版本的技巧。您可以直接更改它们的源,也可以使用如下组合器创建适配器:

-- this is a generally useful combinator
liftEither :: MonadError e m => Either e a -> m a
liftEither = either throwError return

-- this is a combinator specific to your question
liftIOEither :: (MonadError e m, MonadIO m) => IO (Either e a) -> m a
liftIOEither = join . liftIO . liftM liftEither

当然还有ExceptT :: IO (Either e a) -> ExceptT e IO a ; ExceptT . evalSQL并不像 liftIOEither . evalSQL 那样多态,但由于我们在 ExceptT 使用它在这种情况下,键入它可能并不重要。

关于haskell - 如何从这段代码中删除 `case of`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28857745/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com