将IO [FilePath]转换为字符串或字节流

ljs*_*dev 0 haskell haskell-snap-framework

我正在从事这个项目,以与Haskell保持联系并努力寻找简单的例子。

在这种情况下,我想要一个针对Snap的Web请求处理程序,该处理程序返回目录中的文件列表。

我相信我正在尝试使getDirectoryContents返回到Snap想要的Bytestring中。

我最困惑如何处理下一行中的返回值filenames <- getDirectoryContents "data"

import Control.Applicative
import Snap.Core
import Snap.Util.FileServe
import Snap.Http.Server
import System.Directory (getDirectoryContents)

main :: IO ()
main = quickHttpServe site

site :: Snap ()
site =
    ifTop (writeBS "hello world") <|> 
    route [ ("foo", writeBS "bar")
          , ("echo/:echoparam", echoHandler)
          , ("view_root_json_files", listRootFilesHandler)
          ] <|> 
    dir "static" (serveDirectory ".")

echoHandler :: Snap ()
echoHandler = do
    param <- getParam "echoparam"
    maybe (writeBS "must specify echo/param in URL")
          writeBS param

listRootFilesHandler :: Snap ()
listRootFilesHandler = do
    -- read all filenames in /data folders
    filenames <- getDirectoryContents "data"
    writeText filenames
Run Code Online (Sandbox Code Playgroud)

Zet*_*eta 5

由于要使用writeText,因此需要转换[FilePath]Text。幸运的是,Text是的实例Monoid,而列表是的实例Foldable,因此我们可以简单地使用foldMap pack filenames来获取单个文本:

-- import Data.Foldable (foldMap)
-- import Data.Text (pack, Text)

toText :: [FilePath] -> Text
toText = foldMap pack
Run Code Online (Sandbox Code Playgroud)

请注意,您liftIO实际上需要使用IO ain Snap b,因为它Snap是的一个实例MonadIO

listRootFilesHandler :: Snap ()
listRootFilesHandler = do
    filenames <- liftIO $ getDirectoryContents "data"
    writeText $ toText filenames
Run Code Online (Sandbox Code Playgroud)

如果要<br/>在每行之后添加一个换行符FilePath,请添加flip snoc '\n'

toText = foldMap (flip snoc '\n' . pack)
-- toText = foldMap (flip append (pack "<br/>") . pack)
Run Code Online (Sandbox Code Playgroud)