懒惰地评估Haskell中的monadic函数

Cha*_*ham 8 monads haskell lazy-evaluation

我似乎无法弄清楚我遇到的这个问题的解决方法.

我有这样的事情:

  getFilePathForDay :: Day -> IO (Maybe FilePath)

  getFilePathForDays date days = do
      files <- mapM getFilePathForDay $ iterate (addDays 1) date
      return . take days . catMaybes $ files
Run Code Online (Sandbox Code Playgroud)

我试图得到x个有效的文件路径,其中x是我想要的天数,但上面的代码只是永远运行.我在使用monads时遇到过这个问题,我想知道是否有一个解决方法可用于我遇到的这个问题.

谢谢!

ham*_*mar 8

代码永远运行,因为您试图在调用中对无限数量的副作用计算进行排序mapM.

由于您事先并不知道需要运行多少这些计算(如您的使用所示catMaybes),因此您必须将调用getFilePathForDay与其余计算交错.这可以使用unsafeInterleaveIO,但顾名思义,这不是推荐的方法.

您可以手动实现:

getFilePathForDays _ 0 = return []
getFilePathForDays date days = do
    mpath <- getFilePathForDay date
    case mpath of
        Just path -> (path :) <$> remaining (days-1)
        Nothing   -> remaining days
  where
    remaining days = getFilePathForDays (addDays 1 date) days
Run Code Online (Sandbox Code Playgroud)

可能有更优雅的方式,但它现在不是我的意思:)