【发布时间】:2011-10-28 10:21:27
【问题描述】:
这是我在 SO 上的第一篇文章,我对 Haskell 比较陌生,所以请原谅任何失误或我的代码不习惯!
考虑以下两个直观的描述:a, f(a), f(f(a))...
答. 一个列表,包含:a、f 对 a 的应用、f 对 that 的应用、f 对 that...
的应用乙。 一个列表,在第 i 个位置包含 f 到 a 的 i 嵌套应用程序。
我的问题是我在尝试使用 Haskell 中的 iterate 函数来执行 A 时被烧毁了。我的实际应用程序是一个模拟,但下面的人为示例突出了这个问题。
import Control.Monad.State
example :: State Int [[String]]
step :: [String] -> State Int [String]
step l = do
currentState <- get
let result = if (currentState == 1)
then "foo":l
else "bar":l
put (currentState + 1)
return result
example = do
sequence $ take 3 . iterate (>>= step) $ return []
有了这些定义,
evalState example 1
结果:
[[],["foo"],["bar","bar"]]
显然,iterate 是 B,而不是 A!因为step 函数只添加 到输入列表中,所以step ["foo"] 不可能导致["bar", "bar"],无论是什么状态!
让我说我确实了解这里发生了什么,而且 - 正式 - 结果正是“应该是”:step 是一个有状态的函数,所以当f(a) 作为 f(f(a)) 的一部分进行评估,它将被重新计算,而不是从第二个列表项中取出,因为状态已经改变。我也意识到我可以通过将累积列表放入状态中来避免在我的实际应用程序中发生这种情况。
不过,发布此内容有两个原因。
首先,重点是iterate 经常被解释为可能误导初学者认为它是A,而实际上它是B。这包括Learn You A Haskell(否则我发现它非常有用),但也发布在 SO(例如here 和here)。事实上,LYAHFGG中iterate的口头解释几乎就是上面的定义A。因此,在此发布一个帖子可能是有用的,作为其他 Haskell 新手的资源,他们因此而遇到错误并正在寻找解释(因此,一定要发布更准确、技术性、措辞更好的澄清A 和 B 之间的区别)。
其次,我仍然对是否有一个实际上会执行A的函数感兴趣!换句话说,在上面的有状态示例中,我如何生成列表(稍微滥用符号):[a, b = f(a), f(b), ...]?换句话说,给定
example2 = do
firstResult <- step []
secondResult <- step firstResult
return $ [[], firstResult, secondResult]
为了什么
evalState example2 1
产生预期的结果
[[],["foo"],["bar","foo"]]
如何使用iterate 重写example2?
在初学者 Haskell 列表中,发布了一个关于 iterate 的记忆版本的 related question。但是,该查询似乎没有收到答案。
我不完全确定懒惰真的是我的应用程序中的问题。 iterate 的严格版本会做我想要的吗?如下所示,我自己的、幼稚的“严格迭代”似乎没有任何区别。
iterate' f x = x : rest
where previous = f x
rest = previous `seq` iterate f previous
我们将不胜感激任何有关这一切的见解!
【问题讨论】:
标签: haskell iteration loops state-monad