简体   繁体   English

在Haskell中使用Cassava解析文件时创建列表

[英]Creating a list when parsing a file using Cassava in Haskell

I'm able to parse my csv file using the following code from Data.Csv: 我可以使用Data.Csv中的以下代码解析我的csv文件:

valuesToList :: Foo -> (Int, Int)
valuesToList (Foo a b) = (a,b)

loadMyData :: IO ()
loadMyData = do
  csvData <- BL.readFile "mydata.csv"
  case decodeByName csvData of
        Left err -> putStrLn err 
        Right (_, v) -> print $ V.toList $ V.map valuesToList v

When I run this I get the correct output on the screen. 当我运行它时,我在屏幕上得到正确的输出。 The problem I have is I'm not clear how to create a pure function so I can consume the contents of the list, as in: 我遇到的问题是我不清楚如何创建一个纯函数,所以我可以使用列表的内容,如:

let l = loadMyData

Where l is of type [Int,Int] I'm guessing it's because I'm in the IO Monad and I'm doing something hopelessly silly... 其中l的类型为[Int,Int]我猜这是因为我在IO Monad,我正在做一些无可救药的傻事......

I'm doing something hopelessly silly... 我正在做一些无可救药的傻事......

Yes, but worry not! 是的,但不要担心!

loadMyData = BL.readFile "mydata.csv"

processMyData :: String -> String
processMyData csvData = 
  case decodeByName csvData of
        Left err -> err 
        Right (_, v) -> show $ V.toList $ V.map valuesToList v

main = do
    csv <- loadMyData
    let output = processMyData csv
    print output

This way you separate the pure, "let" part from the impure loading part. 这样您就可以将纯粹的“let”部分与不纯的装载部分分开。 This isn't Code Review (if you asked there, I could probably elaborate more), but I'd type the processing as String -> Either String [Int, Int] or something and keep the failure information in the type system. 这不是代码审查(如果你在那里问我,我可能会详细说明),但我将处理类型为String -> Either String [Int, Int]或类似的东西,并将故障信息保存在类型系统中。

processMyData csvData = 
  case decodeByName csvData of
        Left err -> Left err 
        Right (_, v) -> Right $ V.toList $ V.map valuesToList v

And that in turn could simply be (pardon me if I make a mistake somewhere, I'm doing it live ): 而这反过来可能只是(原谅我,如果我在某个地方犯了错误,我正在做它 ):

processMyData = fmap (V.toList . V.map valuesToList) . decodeByName

That should work because of how the Functor instance for Either is constructed. 这应该工作,因为如何构造EitherFunctor实例


Oh, and also use Control.Applicative for bonus style points: 哦,还可以使用Control.Applicative获得奖励样式点:

main = do
    output <- processMyData <$> loadMyData
    print output

(in case you don't understand that example, (<$>) is infix fmap , but that's not stricly necessary; hence bonus ) (如果您不理解该示例, (<$>)是中缀fmap ,但这不是非常必要的;因此奖金

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM