I'm working on this project to get feet wet with Haskell and struggling with finding simple examples.
In this instance, I would like to have a web request handler for Snap, which returns a list of files in a directory.
I believe I'm trying to get the return of getDirectoryContents into a Bytestring which Snap wants.
I am most confused about what to do with the return value I get at the line filenames <- getDirectoryContents "data"
below:
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
Since you want to use writeText
, you need to convert [FilePath]
to Text
. Luckily, Text
is an instance of Monoid
, and a list is a instance of Foldable
, so we can simply use foldMap pack filenames
to get a single text:
-- import Data.Foldable (foldMap)
-- import Data.Text (pack, Text)
toText :: [FilePath] -> Text
toText = foldMap pack
Note that you'll need to use liftIO
to actually use a IO a
in Snap b
, since Snap
is an instance of MonadIO
:
listRootFilesHandler :: Snap ()
listRootFilesHandler = do
filenames <- liftIO $ getDirectoryContents "data"
writeText $ toText filenames
If you want to add a newline (or <br/>
) after each FilePath
, add flip snoc '\n'
:
toText = foldMap (flip snoc '\n' . pack)
-- toText = foldMap (flip append (pack "<br/>") . pack)