理解Haskell中的基本递归

时间:2016-05-12 14:02:46

标签: haskell recursion

我正在编写遗传算法作为人工智能课程的一个项目。我熟悉GA背后的概念,但我对Haskell的经验是有限的。在程序中只剩下一件事要做的事情就是制作一个循环我其他功能的功能。我将介绍我的功能并更详细地解释问题:

这是第二代的功能。我得到了父母,交配它们并改变基因组,然后将新的基因组传递到一个列表中:

<movie-list #future></movie-list>
<movie-list #past></movie-list>

这很有效。我可以创建新一代并重复:

generation1 = initialPopulation
generation2 = [(mutate (mate (fTTS generation1) (sTTS generation1))) | x <- [1..100]]

因此,对于每一代新生代而言,我都更接近目标基因组(在我的情况下是一个字符串)。我希望生成新一代,直到达到目标String。我认为基本的递归可以解决这个问题,如:

generation3 = [(mutate (mate (fTTS generation2) (sTTS generation2))) | x <- [1..100]]

这适用于我的笔记本电脑g(3),但计算需要很长时间。我的问题是我不明白为什么。我认为Haskell递归的工作方式如下:

g 0 = initialPopulation
g n = [(mutate (mate (fTTS (g (n - 1))) (sTTS (g (n - 1))))) | x <- [1..100]]

在我脑海中应该与上面的generation3功能相同。如果有更多了解Haskell的人可以解释为什么我能够毫无困难地运行&#34;生成15&#34; -function但不超过&#34; g(3)&#,我将不胜感激34; -function在我必须在控制台强行退出之前。

谢谢!

1 个答案:

答案 0 :(得分:5)

问题是g n不是 memoized - 它将在列表理解中重新计算2 * 1000

g 0 = initialPopulation
g n = 
    let prev = g (n-1)
    in [(mutate (mate (fTTS prev) (sTTS prev))) | x <- [1..100]]

应该改善一些事情(我想要获得严格的价值也是一个很好的问题 - 但这可能是另一个问题)

但我不会那样使用它 - 而是写一个:

nextGen prev = [(mutate (mate (fTTS prev) (sTTS prev))) | x <- [1..100]]

功能,然后您可以执行以下操作:

find gen = if goodEnough gen then gen else find (nextGen gen)

带着充满希望的

best = find initialPopulation

(请注意,也许你应该在很多代之后都有一个退出策略 - 所以你可能想要包括一代计数器或类似的东西)