如何使用 Haskell Turtle 库打印路径?

How to print paths using Haskell Turtle library?

要学习一点 Turtle,我认为修改教程中的示例会很好。我选择从输出的每一行中删除冗余 "FilePath",认为这将是一个简单的练习。

然而,尽管作者努力使他的库易于使用,但我几乎没能用它来解决这个简单的问题。

我尝试了所有我看到的东西,看起来可以让我以某种方式将 >>=IO 提升到 ShellMonadIOFoldMliftIO_foldIO 没有成功。我变得很沮丧,只有通过阅读 Turtle 源代码,我才能找到似乎可行的东西(想到 "no obvious defects")。

为什么这么难?如何使用此库的 API 从逻辑上得出解决方案?

#!/usr/bin/env stack
-- stack --resolver lts-8.17 --install-ghc runghc --package turtle --package lens
{-# LANGUAGE OverloadedStrings #-}
import Turtle
import Control.Lens
import Control.Foldl as Foldl
import Filesystem.Path.CurrentOS
import Data.Text.IO as T
import Data.Text as T

main = do
  homedir <- home
  let paths = lstree $ homedir </> "projects"
  let t = fmap (Control.Lens.view _Right . toText) paths
  customView t

customView s = sh (do
  x <- s
  liftIO $ T.putStrLn x)

您不会将 >>=IO 提升到 ShellShell 已经有一个 Monad 实例,它自带 >>= 函数。相反,您要么将 IO 操作提升为 ShellliftIO 或 运行 或 shell 与 foldfoldM。当您不关心结果时,使用 sh 到 运行 Shell

我相信你的例子可以简化为

main = sh $ do
  homedir <- home
  filepath <- lstree $ homedir </> "projects"
  case (toText filepath) of
    Right path -> liftIO $ T.putStrLn x
    Left approx -> return () -- This shouldn't happen

至于从 FilePath 获取字符串的困难,我认为这不能归咎于 Turtle 作者。我觉得可以简化为

stringPath :: FilePath -> String
stringPath filepath =
  case (toText filePath) of              -- try to use the human readable version
     Right path -> T.unpack path 
     Left _     -> encodeString filePath -- fall back on the machine readable one

结合这将把例子简化为

main = sh $ do
  homedir <- home
  filepath <- lstree $ homedir </> "projects"
  liftIO $ putStrLn (stringPath filepath)

main = view $ do
  homedir <- home
  filepath <- lstree $ homedir </> "projects"
  return $ stringPath filepath