yoshikit1996’s diary

日々勉強したことの備忘録です。

HaskellでCSVファイルを読み込む

HaskellCSVファイルを読み込むプログラムを書いてみました.

ソースコード

-- CsvReader.hs

module CsvReader where

import Text.Parsec

csvStruct = endBy line eol 
line = sepBy cell $ char ',' 
cell = many $ noneOf ",\n"
eol = char '\n'

parseCSV :: String -> Either ParseError [[String]]
parseCSV src = parse csvStruct "* ParseError *" src

readCSV filePath = do
    cs <- readFile filePath
    case parseCSV cs of
        Right xs -> return xs
        _ -> error "error"

使い方

インポートして「readCSV ファイル名」で,CSVを読み込む.

main = do
    cs <- readCSV "iris.csv"
    putStrLn $ show $ cs

実行結果の例↓

[["5.1","3.5","1.4","0.2","Iris-setosa"],["4.9","3.0","1.4","0.2","Iris-setosa"],["4.7","3.2","1.3","0.2","Iris-setosa"],["4.6","3.1","1.5","0.2","Iris-setosa"],["5.0","3.6","1.4","0.2","Iris-setosa"],["5.4","3.9","1.7","0.4","Iris-setosa"],["4.6","3.4","1.4","0.3","Iris-setosa"],["5.0","3.4","1.5","0.2","Iris-setosa"],["4.4","2.9","1.4","0.2","Iris-setosa"],["4.9","3.1","1.5","0.1","Iris-setosa"],["5.4","3.7","1.5","0.2","Iris-setosa"],["4.8","3.4","1.6","0.2","Iris-setosa"],["4.8","3.0","1.4","0.1","Iris-setosa"],["4.3","3.0","1.1","0.1","Iris-setosa"],["5.8","4.0","1.2","0.2","Iris-setosa"],["5.7","4.4","1.5","0.4","Iris-setosa"],["5.4","3.9","1.3","0.4","Iris-setosa"],["5.1","3.5","1.4","0.3","Iris-setosa"],

... 途中省略 ...

["6.0","3.0","4.8","1.8","Iris-virginica"],["6.9","3.1","5.4","2.1","Iris-virginica"],["6.7","3.1","5.6","2.4","Iris-virginica"],["6.9","3.1","5.1","2.3","Iris-virginica"],["5.8","2.7","5.1","1.9","Iris-virginica"],["6.8","3.2","5.9","2.3","Iris-virginica"],["6.7","3.3","5.7","2.5","Iris-virginica"],["6.7","3.0","5.2","2.3","Iris-virginica"],["6.3","2.5","5.0","1.9","Iris-virginica"],["6.5","3.0","5.2","2.0","Iris-virginica"],["6.2","3.4","5.4","2.3","Iris-virginica"],["5.9","3.0","5.1","1.8","Iris-virginica"]]

ハマった点

副作用の取り扱い

最初,readCSV関数はdo構文なしで書ける思っていたのですが,そうではないみたいです.
基本的に副作用のあるものは,do構文や>>==の中でしか取り扱えないのかな?と思いました.
副作用はモナドの中に閉じ込めているといった印象を持ちました.