0

所以我正在为 CSV 文件编写一个实用函数的小玩具箱,并在整个测试过程中我一直在手动绑定文件

table' <- parseCSVFromFile filepath

但是(从Text.CSV

parseCSVFromFile :: FilePath -> IO (Either parsec-3.1.9:Text.Parsec.Error.ParseError CSV)

所以我不得不写一个快速的行来去掉这个错误 csv 废话

stripBare csv = head $ rights $ flip (:) [] csv

并将其重新定义为table = stripBare table'. 在此之后,列表函数对 csv 文件内容起作用,并且生活继续

(题外话:令人惊讶的是没有直接的Either a b -> b功能Data.Either。所以我使用了Data.Either.rights :: [Either a b] -> [b]

我想一次性完成 csv 类型的脱衣并将其绑定到手柄上的工作。就像是

table = stripBare $ table' <- parseCSVFromFile filepath

但这会在 ( <-) 上给出一个解析错误,说我可能缺少一个do... 然后

table = stripBare $ do table' <- parseCSVFromFile filepath

对我大喊大叫,说do块中的最后一个语句必须是表达式。

我究竟做错了什么?

作为一个单独的好奇心,我在这里看到

以非常简单的方式在 Haskell deugars 中做符号。

do
  x <- foo
  e1 
  e2
  ...

变成

 foo >>= \x ->
 do
   e1
   e2

我觉得这很有吸引力并尝试了以下行,这给了我一个类型错误

*Toy> :type (parseCSVFromFile "~/.csv") >>= \x -> x

<interactive>:1:52: error:
    * Couldn't match type `Either
                             parsec-3.1.9:Text.Parsec.Error.ParseError'
                     with `IO'
      Expected type: IO CSV
        Actual type: Either parsec-3.1.9:Text.Parsec.Error.ParseError CSV
    * In the expression: x
      In the second argument of `(>>=)', namely `\ x -> x'
      In the expression:
        (parseCSVFromFile "~/.csv") >>= \ x -> x
4

1 回答 1

0

代码如

head $ rights $ flip (:) [] csv

很危险。您正在利用 的偏心head来隐藏csv可能是Left something. 我们可以将其重写为

= head $ rights $ (:) csv []
= head $ rights [csv]
= case csv of
     Left _  -> error "Left found!"
     Right x -> x

通常Left情况下最好直接在doIO 块中处理。类似的东西:(伪代码如下)

foo :: String -> IO ()
foo filepath = do
   table' <- parseCSVFromFile filepath
   case table' of
      Left err -> do
         putStrLn "Error in parsing CSV"
         print err
         moreErrorHandlingHere
      Right table -> do
         putStrLn "CSV loaded!"
         use table
于 2017-01-19T11:45:27.937 回答