Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何从此代码中删除'case of'?_Haskell - Fatal编程技术网

Haskell 如何从此代码中删除'case of'?

Haskell 如何从此代码中删除'case of'?,haskell,Haskell,如何重写以下代码,以便: 使用更少的字符 最多包含一个案例。。。属于… --parseSQL::String->ParseError-SQL --evalSQL::SQL->IO(EvalError表之一) --prettyPrintTable::Table->IO() --ParseError、EvalError和Table是Show的实例 evalAndPrint::字符串->IO() evalAndPrint x= 案例解析 (左语法分析器)-> 打印分析器 (右sql)->do 结果 打

如何重写以下代码,以便:

  • 使用更少的字符
  • 最多包含一个
    案例。。。属于…
  • --parseSQL::String->ParseError-SQL
    --evalSQL::SQL->IO(EvalError表之一)
    --prettyPrintTable::Table->IO()
    --ParseError、EvalError和Table是Show的实例
    evalAndPrint::字符串->IO()
    evalAndPrint x=
    案例解析
    (左语法分析器)->
    打印分析器
    (右sql)->do
    结果
    打印错误
    (右表)->do
    预打印表格
    putStrLn$“(“++显示(长度表)++”行)\n”
    
    现在,让我们假设您已经将
    parseSQL
    evalSQL
    函数概括为这些类型(稍后我们将看到如何将您的专用实现转化为通用实现,即使您无法访问它们的源代码):

    然后我们可以写:

    -- 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"
    

    当然还有
    ExceptT::IO(ea)->exceptteioa
    <代码>例外。evalSQL也不像
    liftio那样具有多态性。evalSQL
    ,但由于我们在
    例外的
    类型上使用它,所以在这种情况下它可能并不重要。

    看起来像是
    error
    EitherT
    或其他一些错误monad转换器的完美候选。您几乎可以直接使用
    monad
    实例来实现这一点。不幸的是,
    evalSQL
    有点搞砸了。因此,看起来您需要
    EitherT
    或其他什么……这也很困难,因为在每种情况下使用的两个monad实例都是不同的。第一个Orther monad实例是
    Orther ParseError
    ,第二个是
    Orther EvalError
    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 ()
    
    -- 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