通过迭代Haskell中

时间:2017-12-23 10:14:42

标签: haskell

对Haskell来说是全新的我认为编写一个小实用工具将是学习它的良好开端。我的目标是实现某种类型的Linux"更多"用于显示PK压缩存档文件内容的命令。到目前为止,我只设法列出档案中的文件名:

module Main where

import Codec.Archive.Zip
import Path
import Path.IO (resolveFile')
import Data.List (sortBy)
import Data.Ord (comparing)
import qualified Data.Map as Map
import qualified Data.ByteString.Char8 as Byte (ByteString)

loadTicks :: Path Abs File -> EntrySelector -> IO Byte.ByteString
loadTicks ticksArchivePath entry = withArchive ticksArchivePath (getEntry entry)

extractEntries :: Path Abs File -> IO [EntrySelector]
extractEntries ticksArchivePath = withArchive ticksArchivePath loadEntries

loadEntries :: ZipArchive [EntrySelector]
loadEntries = fmap Map.keys getEntries

-- not really useful since only natural ordering is required
customSort :: Ord a => a -> a -> Ordering
customSort elem1 elem2 = compare elem1 elem2

main :: IO ()
main = do
    let ticksArchivePath = resolveFile' "data/data-small.zip" :: IO (Path Abs File)  
    let entries = extractEntries =<< ticksArchivePath :: IO [EntrySelector]  
    sortedEntries <- fmap (sortBy customSort) entries :: IO [EntrySelector]
    print sortedEntries

我现在陷入困境,因为我无法弄清楚如何在loadTicks中的每个条目上调用sortedEntries函数。我怎么能这样做才能最终获得一个[String]输出来连接存档的每个文件中的所有行(示例存档: https://drive.google.com/open?id=1mp1TIPmJd74SGJ4Yy5J-BBsoyBPPPHRh)?

修改

@arrowd评论后,以下代码有效:

{-# LANGUAGE OverloadedStrings #-}
module Main where

import Codec.Archive.Zip
import Path
import Path.IO (resolveFile')
import Data.List (sortBy)
import Data.Text (takeEnd)
import Data.Ord (comparing)
import Prelude hiding (concat)
import Data.ByteString.Char8 (concat)
import qualified Data.Map as Map
import qualified Data.ByteString.Char8 as Byte (ByteString)

loadTicks :: Path Abs File -> EntrySelector -> IO Byte.ByteString
loadTicks ticksArchivePath entry = withArchive ticksArchivePath (getEntry entry)

extractEntries :: Path Abs File -> IO [EntrySelector]
extractEntries ticksArchivePath = withArchive ticksArchivePath loadEntries

loadEntries :: ZipArchive [EntrySelector]
loadEntries = fmap Map.keys getEntries

-- not really useful since only natural ordering is required
customSort :: Ord a => a -> a -> Ordering
customSort elem1 elem2 = compare elem1 elem2

isCSVFile :: EntrySelector -> Bool
isCSVFile entry = takeEnd 4 (getEntryName entry) == ".csv"

main :: IO ()
main = do
    ticksArchivePath <- resolveFile' "data/data-small.zip" :: IO (Path Abs File)
    entries <- extractEntries ticksArchivePath :: IO [EntrySelector]
    let sortedEntries = sortBy customSort entries :: [EntrySelector]
    let ticks = loadTicks ticksArchivePath
    contents <- mapM ticks sortedEntries :: IO [Byte.ByteString]
    print (concat contents)

1 个答案:

答案 0 :(得分:1)

根据经验,箭头<-“从某些a中拉出”m a,其中m是Monad。在这种情况下,do-block的箭头会从a s中拉出IO a

因此,要摆脱fmaps,你应该写

ticksArchivePath <- resolveFile' "data/data-small.zip" :: IO (Path Abs File)

而不是

let ticksArchivePath = resolveFile' "data/data-small.zip" :: IO (Path Abs File) 

entries <- extractEntries ticksArchivePath :: IO [EntrySelector]

而不是

let entries = extractEntries =<< ticksArchivePath :: IO [EntrySelector]

在do-blocks中以let开头的表达式通常用于纯计算。在你的情况下它是

let sortedEntries = sortBy customSort entries

StackOverflow文档有一个很棒的部分解释了monad和do-syntax,但是唉,它现在已经消失了。