could you please help me with Turtle library. I want to write simple program, that calculates disk space usage. Here is the code:
getFileSize :: FilePath -> IO Size
getFileSize f = do
status <- stat f
return $ fileSize status
main = sh $ do
let sizes = fmap getFileSize $ find (suffix ".hs") "."
so now I have sizes bind of type Shell (IO Size). But I can't just sum it, with sum fold, cause there is IO Size in there. If it was something like [IO Size] I could pull IO monad out of there by using sequence to transform it to IO [Size]. But I can't do this with Shell monad since it is not Traversable. So I wrote something like this
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))
First I folded Shell (IO Size) to [IO Size] and then to IO [Size] to sum list afterwards.
But I wonder if there is more canonical or elegant solution to this, because here I created two lists to accomplish my task. And I throught that Shell monad is for manipulating entities in constant space. Maybe there is some fold to make IO (Shell Size) from Shell (IO Size)?
Thanks.
You have an
IOaction, and you really want aShellaction. The usual way to handle that is with theliftIOmethod, which is available becauseShellis an instance ofMonadIO.or even
Fortunately, the
Turtlepackage itself offers some size functions you can use directly withMonadIOinstances likeShellinTurtle.Preludeso you don't need to useliftIOyourself.Now you actually have to sum these up, but you can do that with
foldandsum.I would recommend that you avoid breaking open the
Shelltype itself. That should be reserved for adding totally new functionality to the API. That certainly isn't necessary in this case.