请帮助我使用Turtle库。 我想编写一个简单的程序来计算磁盘空间使用率。 这是代码:
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
将sequence
转换为IO [Size]
来将其移出。但是我不能使用Shell
单子执行此操作,因为它不是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]
以汇总清单。
但是我想知道是否还有其他规范或优雅的解决方案,因为在这里我创建了两个列表来完成我的任务。我认为Shell
monad是用于在恒定空间中操纵实体的。也许有一些fold
是用IO (Shell Size)
来制作Shell (IO Size)
的?
谢谢。
答案 0 :(得分:0)
实际上,我已经通过使用辅助转换成功地摆脱了uname -a
IO
但是现在我想知道有没有更简单的解决方案...
答案 1 :(得分:0)
您有一个IO
动作,而您确实想要一个Shell
动作。处理该问题的常用方法是使用liftIO
方法,因为Shell
是MonadIO
的实例,所以该方法可用。
file <- find (suffix ".hs") "."
size <- liftIO $ getFileSize file
甚至
size <- liftIO . getFileSize =<< find (suffix ".hs") "."
幸运的是,Turtle
包本身提供了一些大小函数,可以直接与MonadIO
in Turtle.Prelude
之类的Shell
实例使用,因此您无需使用{{1 }}自己。
现在您实际上必须对它们进行总结,但是您可以使用liftIO
和fold
来做到这一点。
我建议您避免自行打开sum
类型。应该保留该功能,以便为API添加全新的功能。在这种情况下,那当然不是必需的。