2013-10-06 2 views
0

Я пытаюсь преобразовать файл CSV изСинтаксический .csv в пунктах в Haskell

femin,femin,1,f,woman,women, 
aqu,aqu,1,f,water,waters, 
.. 

в файл .pl как

noun(femin,femin,1,f,trans(woman,women)). 
noun(aqu,aqu,1,f,trans(water,waters)). 
.. 

здесь мой текущий исходный код:

-- get from "femin, femin, 1, f, woman, women" to noun(femin, femin, 1, f ,trans(woman,women)). 
import qualified Data.Attoparsec as P 


data NounClause = NounClause 
    { 
     nom :: String, 
     gen :: String, 
     declension :: String, 
     gender :: String, 
     sgtrans :: String, 
     pltrans :: String 
    } deriving Show 

parseNounClause :: P.Parser NounClause 

parseNounClause = do 
    nom <- String 
    char "," 
    gen <- String 
    char "," 
    declension <- String 
    char "," 
    gender <- String 
    char "," 
    sgtrans <- String 
    char "," 
    pltrans <- String 
    return $ NounClause nom gen declension gender sgtrans pltrans 

Однако, похоже, что это не работает. Почему это так?

Также, как я могу применить этот синтаксический анализатор к каждой строке? Здесь также моя функция, которая принимает анализируемые данные и возвращает строку.

c = "," 
convert :: NounClause -> String 
convert NounClause = "noun(" ++ nom ++ C++ gen ++ C++ declension ++ C++ gender ++ "trans(" ++ sgtrans ++ C++ pltrans ++ "))." 

Я очень благодарен всем, кто помогает мне в этом проекте; их вклад является самым ценным для меня.

+0

Кстати, я рекомендую проверить [маниока] (http://hackage.haskell.org/package/cassava-0.2.2.0/docs/Data-Csv.html) или какой-либо другой CSV, если вы разбираете документы CSV. – kqr

+0

Большое спасибо, я посмотрю на него – user2850249

ответ

2

Если вы используете синтаксический анализатор String, он пытается использовать как можно больше ввода. Сюда входят запятые в вашем файле. Итак, вы создаете парсер, который читает все, кроме запятых.

import qualified Data.Attoparsec.Text as P 
import Data.Text(unpack) 

entry = fmap unpack (P.takeWhile (/=',')) 

распаковывать используются для преобразования разобранной информации типа Text в строку.

Затем вам нужен дополнительный парсер, который читает запятую.

separator = P.char ',' 

Тогда мы объединяем это разобрать NounClause

parseNounClause :: P.Parser NounClause 
parseNounClause = do 
    nom <- entry 
    separator -- don't need the comma so no need to keep it. 
    gen <- entry 
    separator 
    declension <- entry 
    separator 
    gender <- entry 
    separator 
    sgtrans <- entry 
    separator 
    pltrans <- entry 
    separator 
    return $ NounClause nom gen declension gender sgtrans pltrans 

Итак, теперь вы хотите, чтобы прочитать несколько строк. Это то же самое, что и запятая, но теперь с символом новой строки. Мы анализируем запись и символ новой строки. Чтобы компенсировать n строк, но только n-1 символов новой строки, мы делаем различие для первой строки. Комбинатор many' позволяет нам анализировать нуль или более строк одного формата.

multiLines = do x <- parseNounClause 
       xs <- many' (do P.endOfLine 
           clause <- parseNounClause 
           return clause 
          ) 
       return (x:xs) 

Так что теперь нам нужно разобрать это. Это делается с помощью следующей основной функции. За что нам нужен другой импорт, чтобы прочитать Fileinfo от типа Text

import qualified Data.Text.IO as T(readFile) 

main :: IO() 
main = do fileContents <- T.readFile "input.txt" 
      let result = P.parseOnly multiLines fileContents 
      case result of (Left s) -> putStrLn s 
         (Right rs) -> sequence_ (map (putStrLn . show) rs) 

В результате синтаксического анализа получит нам либо сообщение об ошибке или все NounClause с в списке. Я использую sequence_ (map (putStrLn .show), чтобы распечатать его.

У вас есть функция шоу, которое может преобразовать тип данных в String, потому что вы добавили deriving Show в конце определения, если вы хотите использовать свое собственное String представление экземпляр типа класса самостоятельно (вместо вашей convert функции) как:

instance Show NounClause where 
    show n = ... 
+0

Также у вас уже есть функция, которая возвращает строку.Он называется 'show' ans, созданный' выводить Show'. Если вы хотите иметь собственный формат, вы должны создать экземпляр своего экземпляра Typeclass Show и не выводить его. – MoFu

+0

Большое спасибо MoFu. Однако я не понимаю, что вы имеете в виду в своем комментарии. – user2850249

+0

@ user2850249 у вас есть функция преобразования, которая преобразует вашу структуру данных в строку. Вы также добавили 'выводить Show' за определение типа данных. Из-за этого у вас есть функция 'show :: NounClause -> String', которую большинство людей будет использовать для преобразования чего-то в String. Если вы хотите создать собственное шоу, вам лучше создать экземпляр собственного класса. Показать тип статьи http://book.realworldhaskell.org/read/using-typeclasses.html) – MoFu

Смежные вопросы