【发布时间】:2013-01-24 05:34:27
【问题描述】:
通过Listing all the contents of a directory by breadth-first order results in low efficiency我了解到效率低下是由于递归单子函数的奇怪行为。
试试
sequence $ map return [1..]::[[Int]]
sequence $ map return [1..]::Maybe [Int]
而ghci会陷入无休止的计算中。
如果我们将序列函数重写为更易读的形式,如下所示:
sequence' [] = return []
sequence' (m:ms) = do {x<-m; xs<-sequence' ms; return (x:xs)}
并尝试:
sequence' $ map return [1..]::[[Int]]
sequence' $ map return [1..]::Maybe [Int]
我们遇到同样的情况,一个无限循环。
尝试一个有限列表
sequence' $ map return [1..]::Maybe [Int]
经过长时间的等待,它会弹出预期的结果Just [1,2,3,4..]。
通过我们的尝试,我们可以得出结论,虽然sequence'的定义看起来很懒惰,但它是严格的,必须在打印sequence'的结果之前把所有的数字都弄出来。
不仅仅是序列',如果我们定义一个函数
iterateM:: Monad m => (a -> m a) -> a -> m [a]
iterateM f x = (f x) >>= iterateM0 f >>= return.(x:)
试试
iterateM (>>=(+1)) 0
然后进行无休止的计算。
众所周知,non-monadic iterate的定义和上面的iterateM一样,但是为什么iterate是lazy的,iterateM是strict的。 从上面我们可以看出,iterateM和sequence'都是递归monadic函数。递归monadic函数有什么奇怪的地方
【问题讨论】:
标签: loops haskell recursion monads lazy-evaluation