Ошибки Haskell при привязке CSV-файла к дескриптору

Итак, я написал небольшой набор служебных функций для 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, и жизнь продолжается.

(Отступление: на удивление, в Data.Either нет прямой функции Either a b -> b. Поэтому я использовал Data.Either.rights :: [Either a b] -> [b])

Я хотел выполнить работу по раздеванию типа csv и привязке его к ручке за один раз. Что-то вроде

table = stripBare $ table' <- parseCSVFromFile filepath

но это дает ошибку синтаксического анализа на (<-), говоря, что мне может не хватать do... тогда

table = stripBare $ do table' <- parseCSVFromFile filepath

кричит на меня, говоря, что последний оператор в блоке do должен быть выражением.

Что я делаю не так?

В качестве отдельного любопытства я увидел здесь, что

сделать нотацию в Haskell desugars довольно простым способом.

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

person Tshimanga    schedule 19.01.2017    source источник
comment
Неудивительно, что Either a b -> b не существует. Если у вас есть a, но нет b, какой b вы бы произвели?   -  person molbdnilo    schedule 19.01.2017
comment
Ах да, верно. Списки допускают отсутствие @molbdnilo   -  person Tshimanga    schedule 19.01.2017


Ответы (1)


Код, например

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 непосредственно в блоке ввода-вывода do. Что-то вроде: (следует псевдокод)

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
person chi    schedule 19.01.2017