gpt4 book ai didi

Haskell Turtle - 劈开一个壳

转载 作者:行者123 更新时间:2023-12-02 21:07:23 27 4
gpt4 key购买 nike

是否可以在 Turtle 库(Haskell)中拆分 Shell,并对任一拆分的 Shell 执行不同的操作,以便原始 Shell 只运行一次?

             /---- shell2
---Shell1 --/
\
\-----shell3

例如,如何做

do
let lstmp = lstree "/tmp"
view lstmp
view $ do
path <- lstmp
x <- liftIO $ testdir path
return x

这样 lstree "/tmp"只会运行一次。

具体来说,我想使用输出将 Shell 2 和 Shell 3 发送到不同的文件。

最佳答案

您将无法拆分 Shell进入两个同时运行的独立外壳,除非有一些我不知道的魔法。但是文件写入是 shell 或其他一些连续事物的内容的折叠。它内置于 turtle您始终可以组合多个折叠并使用 Control.Foldl 让它们同时运行 Material - 这里

foldIO ::  Shell a -> FoldM IO a r -> IO r  -- specializing

shell secret 是 FoldM IO a r -> IO r无论如何,这基本上是 runShell 。为此,我们需要获得正确的 Shell和右边组合FoldM IO 。整体思路Fold a bFoldM m a b来自 foldl 的类型包装同时折叠。

我认为获得正确 shell 的最简单方法就是制作 lstree折叠返回 FilePath 一起,结果为 testdir 。你基本上是这样写的:

withDirInfo :: FilePath -> Shell (Bool, FilePath)
withDirInfo tmp = do
let lstmp = lstree tmp
path <- lstmp
bool <- liftIO $ testdir path
return (bool, path)

现在我们可以得到 Shell (Bool, FilePath)来自/tmp这包含了我们的两个折叠所需的所有信息,因此我们的组合折叠也需要。

接下来我们可能会编写一个辅助折叠来打印 Text FilePath的组成部分到给定的句柄:

sinkFilePaths :: Handle -> FoldM IO FilePath ()
sinkFilePaths handle = L.sink (T.hPutStrLn handle . format fp)

然后我们可以使用这个Handle -> FoldM IO FilePath ()定义两个FoldM IO (Bool, FilePath) () 。每个都会向不同的句柄写入不同的内容,我们可以使用 <* 将它们合并到一个同时折叠中。 。这是一个独立的FoldM IO ...并且可以应用例如到类型 [(Bool, FilePath)] 的纯列表使用L.fold它会将列表中的不同内容写入不同的句柄。但在我们的例子中,我们将把它应用到 Shell (Bool, FilePath)我们定义了。

其中唯一微妙的部分是 L.handlesM 的使用在这两种情况下仅打印第二个元素,并且仅打印在另一种情况下过滤为目录的元素。这使用 _2镜头和filtered来自镜头库。这可能可以简化,但看看你的想法:

{-#LANGUAGE OverloadedStrings #-}
import Turtle
import qualified Control.Foldl as L
import qualified System.IO as IO
import Control.Lens (_2,filtered)
import qualified Data.Text.IO as T

main = IO.withFile "tmpfiles.txt" IO.WriteMode $ \h ->
IO.withFile "tmpdirs.txt" IO.WriteMode $ \h' -> do
foldIO (withDirInfo "/tmp") (sinkFilesDirs h h')

withDirInfo :: Turtle.FilePath -> Shell (Bool, Turtle.FilePath)
withDirInfo tmp = do
let lstmp = lstree tmp
path <- lstmp
bool <- liftIO $ testdir path
return (bool, path)

sinkFilePaths :: Handle -> FoldM IO Turtle.FilePath ()
sinkFilePaths handle = L.sink (T.hPutStrLn handle . format fp)

sinkFilesDirs :: Handle -> Handle -> FoldM IO (Bool, Turtle.FilePath) ()
sinkFilesDirs h h' = allfiles <* alldirs where

allfiles :: L.FoldM IO (Bool, Turtle.FilePath) ()
allfiles = L.handlesM _2 (sinkFilePaths h)
-- handle the second element of pairs with sinkFilePaths

alldirs :: FoldM IO (Bool, Turtle.FilePath) ()
alldirs = L.handlesM (filtered (\(bool,file) -> bool) . _2) (sinkFilePaths h')
-- handle the second element of pairs where the first element
-- is true using sinkFilePaths

关于Haskell Turtle - 劈开一个壳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37324186/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com