【问题标题】:Haskell Turtle get out of Shell MonadHaskell Turtle 离开 Shell Monad
【发布时间】:2018-07-24 08:08:52
【问题描述】:

您能帮我处理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],我可以使用sequenceIO monad 从那里拉出来,将其转换为IO [Size]。但我不能用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 用于在恒定空间中操作实体。也许有一些fold 可以从Shell (IO Size) 变成IO (Shell Size)

谢谢。

【问题讨论】:

    标签: haskell haskell-turtle


    【解决方案1】:

    您有一个IO 操作,并且您确实想要一个Shell 操作。通常的处理方法是使用liftIO 方法,因为ShellMonadIO 的一个实例。

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

    甚至

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

    幸运的是,Turtle 包本身提供了一些大小函数,您可以直接与 MonadIO 实例一起使用,例如 Shell in Turtle.Prelude,因此您不需要自己使用 liftIO

    现在您实际上必须总结这些,但您可以使用 foldsum 来做到这一点。

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

    【讨论】:

    • 谢谢,我猜我自己应该是​​这么简单的解决方案。那是因为我把自己困在fmap 中,应该使用更直接的方法。
    【解决方案2】:

    实际上我已经通过使用辅助转换在这里摆脱了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))
    

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

    【讨论】:

      猜你喜欢
      • 2012-10-31
      • 1970-01-01
      • 2013-05-16
      • 2016-08-12
      • 1970-01-01
      • 1970-01-01
      • 2018-03-15
      • 1970-01-01
      • 2013-08-15
      相关资源
      最近更新 更多