Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
惰性地评估Haskell中的一元函数_Haskell_Monads_Lazy Evaluation - Fatal编程技术网

惰性地评估Haskell中的一元函数

惰性地评估Haskell中的一元函数,haskell,monads,lazy-evaluation,Haskell,Monads,Lazy Evaluation,我似乎想不出一个解决这个问题的办法 我有这样的想法: getFilePathForDay :: Day -> IO (Maybe FilePath) getFilePathForDays date days = do files <- mapM getFilePathForDay $ iterate (addDays 1) date return . take days . catMaybes $ files getFilePathForDay::

我似乎想不出一个解决这个问题的办法

我有这样的想法:

  getFilePathForDay :: Day -> IO (Maybe FilePath)

  getFilePathForDays date days = do
      files <- mapM getFilePathForDay $ iterate (addDays 1) date
      return . take days . catMaybes $ files
getFilePathForDay::Day->IO(可能是FilePath)
getFilePathForDays日期天数=do

文件代码将永远运行,因为在调用
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
getFilePathForDays\u0=return[]
getFilePathForDays日期天数=do
mpath(路径:)剩余(第1天)
无->剩余天数
哪里
剩余天数=getFilePathForDays(addDays 1日期)天

也许有一种更优雅的方法,但我现在还没有想到:)

有时候懒惰IO是正确的方法。由于您有一个无限的、惰性的天数序列,并且您正在惰性地对该序列中的某些(动态)范围进行采样,因此我们也应该只按需访问文件系统

这可以通过
unsafeInterleaveIO
完成:

import System.IO.Unsafe         ( unsafeInterleaveIO )

-- return a lazy list of filepaths, pull as many as you need
getFilePathForDays :: Day -> Int -> IO [FilePath]
getFilePathForDays date days = do

    let go (d:ds) = unsafeInterleaveIO $ do
                        f  <- getFilePathForDay d
                        fs <- go ds
                        return (f:fs)

    -- an infinite, lazy stream of filepaths
    fs <- go (iterate (addDays 1) date)

    return . take days . catMaybes $ fs
import System.IO.Unsafe(unsafeInterleaveIO)
--返回文件路径的延迟列表,根据需要提取任意数量的文件路径
getFilePathForDays::Day->Int->IO[FilePath]
getFilePathForDays日期天数=do
放手(d:ds)=不插手$do

为什么这需要在IO单子中?您正在测试文件是否存在?如果是这样的话,在生成文件路径之后就不能这样做吗?@Robin Green:也许Ratzes想从给定日期开始查找第一个
n
现有文件。通过模式匹配在Maybes上生成列表听起来像是一个展开;也许有一种优雅的表达方式?@Dan:这也是我最初的想法,但不是很琐碎。我们想继续下去,直到我们得到一定数量的
s,过滤掉
s,而不是在第一个
@Dan:是的,有一元序列展开,但在这种情况下,我们需要一个展开函数(生成路径)和一个折叠函数(只计算
个数,并根据需要读取尽可能多的数据),两者都有副作用,需要以正确的方式交错。一个优雅的泛化当然存在,但它可能有一个神秘的名称,并且在
类别附加程序包中。我们在标准库中的某个地方没有一个unfolm,这真是太傻了。中有一个。但是,是的,可能是一个很好的基础候选。如果你u将懒惰IO提取到一个函数中,比如
lazyMapIO f(a:as)=unsafeInterleaveIO$do b a
lazySequenceIO
通常非常方便,但当然,由于(完全正确,但仍然…)的“懒惰IO是邪恶的”,它永远也不会进入基础暴民,除了我实际写的代码外,我在各个方面都同情他们:-)