0

你能帮我看看海龟图书馆吗?我想编写一个简单的程序来计算磁盘空间使用情况。这是代码:

getFileSize :: FilePath -> IO Size
getFileSize f = do
  status <- stat f
  return $ fileSize status

main = sh $ do
  let sizes = fmap getFileSize $ find (suffix ".hs") "."

所以现在我有sizes绑定类型Shell (IO Size)。但我不能用sum折叠来总结它,因为那里IO Size有。如果它是类似的东西,[IO Size]我可以IO通过使用将 monadsequence转换为IO [Size]. 但我不能用Shellmonad 做到这一点,因为它不是Traversable. 所以我写了这样的东西

import qualified Control.Foldl as F

main = sh $ do
  let sizes = fmap getFileSize $ find (suffix ".hs") "."
  lst <- fold sizes F.list
  let cont = sequence lst
  sz <- liftIO $ cont
  liftIO $ putStrLn (show (sum sz))  

首先我折叠Shell (IO Size)[IO Size],然后再折叠到IO [Size]总和列表。但我想知道是否有更规范或优雅的解决方案,因为在这里我创建了两个列表来完成我的任务。而且我认为Shellmonad 用于在恒定空间中操纵实体。也许有一些可以fold做?IO (Shell Size)Shell (IO Size)

谢谢。

4

2 回答 2

0

IO实际上我已经通过使用辅助转换来摆脱这里

sio :: Shell (IO a) -> Shell a
sio s = Shell (\(FoldShell step begin done) ->
                let step' x a = do
                      a' <- a
                      step x a'
                in
                  _foldShell s (FoldShell step' begin done))

但现在我想知道这个任务有没有更简单的解决方案......

于 2018-07-24T20:01:42.350 回答
0

你有一个IO动作,你真的想要一个Shell动作。处理这个问题的常用方法是使用liftIO方法,因为它ShellMonadIO.

file <- find (suffix ".hs") "."
size <- liftIO $ getFileSize file

甚至

size <- liftIO . getFileSize =<< find (suffix ".hs") "."

幸运的是,Turtle包本身提供了一些 size 函数,您可以直接将其与inMonadIO等实例一起使用,因此您无需自己使用。Shell Turtle.PreludeliftIO

现在你实际上必须总结这些,但你可以用foldand来做到这一点sum

我建议您避免打开Shell类型本身。这应该保留用于向 API 添加全新的功能。在这种情况下,这当然不是必需的。

于 2018-07-24T20:46:32.650 回答