对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)
答案 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,但是唉,它现在已经消失了。