0

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

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

我尝试了所有我看到的看起来可以让我以某种方式>>=从: , ,提升IO的方法,但没有成功。我变得沮丧,只有通过阅读源代码,我才能找到似乎有效的东西(我想到了“没有明显的缺陷”)。ShellMonadIOFoldMliftIO_foldIOTurtle

为什么这么难?使用该库的 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)
4

1 回答 1

3

你不会>>=IO进入Shell. Shell已经有一个Monad带有自己>>=功能的实例。相反,您可以将IO操作提升到Shellwith或使用liftIOor 运行 shell 。当您不关心结果时使用。foldfoldMshShell

我相信您的示例可以简化为

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

至于从 a 中获取字符串的困难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
于 2017-07-14T01:54:39.760 回答