我正在尝试编写代码以在 Haskell 中执行以下简单任务:使用该字典查找单词的词源,存储为一个大的 tsv 文件(http://www1.icsi.berkeley.edu/~demelo/etymwn/)。我想我会(使用 attoparsec)将 tsv 文件解析为一个 Map,然后我可以根据需要使用它来有效地查找词源(并做一些其他的事情)。
这是我的代码:
{-# LANGUAGE OverloadedStrings #-}
import Control.Arrow
import qualified Data.Map as M
import Control.Applicative
import qualified Data.Text as DT
import qualified Data.Text.Lazy.IO as DTLIO
import qualified Data.Text.Lazy as DTL
import qualified Data.Attoparsec.Text.Lazy as ATL
import Data.Monoid
text = do
x <- DTLIO.readFile "../../../../etymwn.tsv"
return $ DTL.take 10000 x
--parsers
wordpair = do
x <- ATL.takeTill (== ':')
ATL.char ':' *> (ATL.many' $ ATL.char ' ')
y <- ATL.takeTill (\x -> x `elem` ['\t','\n'])
ATL.char '\n' <|> ATL.char '\t'
return (x,y)
--line of file
line = do
a <- (ATL.count 3 wordpair)
case (rel (a !! 2)) of
True -> return . (\[a,b,c] -> [(a,c)]) $ a
False -> return . (\[a,b,c] -> [(c,a)]) $ a
where rel x = if x == ("rel","etymological_origin_of") then False else True
tsv = do
x <- ATL.many1 line
return $ fmap M.fromList x
main = (putStrLn . show . ATL.parse tsv) =<< text
它适用于少量输入,但很快就会变得太低效。我不太清楚问题出在哪里,并且很快意识到,即使是像查看文件的最后一个字符这样的琐碎任务,在我尝试时也会花费太长时间,例如
foo = fmap DTL.last $ DTLIO.readFile "../../../../etymwn.tsv
所以我的问题是:在方法和执行方面,我做错的主要事情是什么?有关更多 Haskelly/更好代码的任何提示?
谢谢,
鲁本