Haskell Turtle 滚出 Shell Monad
Haskell Turtle get out of Shell Monad
你能帮我 Turtle 图书馆吗?
我想编写简单的程序,计算磁盘 space 使用情况。
这是代码:
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]
的东西,我可以通过使用 sequence
将其转换为 IO [Size]
来从那里拉出 IO
monad。但是我不能用 Shell
monad 来做到这一点,因为它不是 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 用于以常量 space 操纵实体。也许有一些 fold
从 Shell (IO Size)
变成 IO (Shell Size)
?
谢谢。
实际上,我在这里通过使用辅助转换
设法摆脱了 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))
但现在我想知道是否有更简单的解决方案来完成此任务...
您有一个 IO
动作,并且您确实想要一个 Shell
动作。通常的处理方法是使用 liftIO
方法,该方法可用是因为 Shell
是 MonadIO
.
的一个实例
file <- find (suffix ".hs") "."
size <- liftIO $ getFileSize file
甚至
size <- liftIO . getFileSize =<< find (suffix ".hs") "."
幸运的是,Turtle
包本身提供了一些大小函数,您可以直接使用 MonadIO
实例,例如 Shell
in Turtle.Prelude
,因此您不需要使用 liftIO
你自己。
现在你实际上必须总结这些,但你可以用 fold
和 sum
来做。
我建议您避免破坏 Shell
类型本身。这应该保留用于向 API 添加全新的功能。在这种情况下当然没有必要。
你能帮我 Turtle 图书馆吗? 我想编写简单的程序,计算磁盘 space 使用情况。 这是代码:
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]
的东西,我可以通过使用 sequence
将其转换为 IO [Size]
来从那里拉出 IO
monad。但是我不能用 Shell
monad 来做到这一点,因为它不是 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 用于以常量 space 操纵实体。也许有一些 fold
从 Shell (IO Size)
变成 IO (Shell Size)
?
谢谢。
实际上,我在这里通过使用辅助转换
设法摆脱了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))
但现在我想知道是否有更简单的解决方案来完成此任务...
您有一个 IO
动作,并且您确实想要一个 Shell
动作。通常的处理方法是使用 liftIO
方法,该方法可用是因为 Shell
是 MonadIO
.
file <- find (suffix ".hs") "."
size <- liftIO $ getFileSize file
甚至
size <- liftIO . getFileSize =<< find (suffix ".hs") "."
幸运的是,Turtle
包本身提供了一些大小函数,您可以直接使用 MonadIO
实例,例如 Shell
in Turtle.Prelude
,因此您不需要使用 liftIO
你自己。
现在你实际上必须总结这些,但你可以用 fold
和 sum
来做。
我建议您避免破坏 Shell
类型本身。这应该保留用于向 API 添加全新的功能。在这种情况下当然没有必要。