Haskell我的递归崩溃

时间:2017-11-29 20:40:22

标签: haskell recursion

您好我是初学者,我尝试在Haskell中学习递归 但我的递归功能不会给我一个解决方案,我的电脑冻结。这是我的功能。我希望我的函数得到一个数字,然后用1减去它。 每次减去数字时,它都会被添加到以0开头的列表中。例如 我们3 = [0,3,2,1]

we w 
   |w == 0 = []
   |w >0 = te [0] w w
   |w <0 = error "test"
   |otherwise = error "test"
   where
te (x:xs) f c = te (x:f:xs) (f-1) (c-1)
te (x:xs) f 0 = x:xs 
te (x:xs) 0 c = x:xs 
te (x:xs) 0 0 = x:xs

1 个答案:

答案 0 :(得分:4)

您的功能存在一些问题,但目前只是程序冻结的原因:

  1. te (x:xs) f c = ...是一种匹配几乎所有可能性的模式:第一个参数为非空列表的所有调用都将匹配,其余子句将永远不会“触发”,因为这些是第一个子句的子集模式;和
  2. 当我们采用第一个子句时,我们将使用正在增长的列表执行递归。我们无法进入基本情况(因为第一项),但我们最终也会耗尽内存。
  3. 你的功能也有一些奇怪的东西(没错,但效率不高或优雅):

    1. 您在f函数中使用cte,但这些值始终具有相同的值;和
    2. 您与w > 0w < 0w == 0进行比较,否则,这很奇怪,因为价值不可能大于,不小于和不小于在同一时间平等。
    3. 所以也许我们应该先回到绘图板。第一步或多或少是一个好的:我们定义函数we,我们区分三种情况:

      we w | w > 0 = ...
           | w == 0 = ...
           | otherwise = ...
      

      显然(这不在您发布的规范中),我们应该在w < 0上出错,并在w等于零的情况下返回一个空列表,所以:

      we w | w > 0 = ...
           | w == 0 = []
           | otherwise = error "w is less than zero"
      

      现在w > 0我们知道我们会生成一个以0开头的列表,后跟别的东西,所以我们可以写:

      we w | w > 0 = 0 : ...
           | w == 0 = []
           | otherwise = error "w is less than zero"
      

      因此我们构建了一个列表(_:_),其中0为头。现在剩下的就是调用递归函数(例如te):

      we w | w > 0 = 0 : te w
           | w == 0 = []
           | otherwise = error "w is less than zero"
          where te n = ...
      

      现在te有两种可能性:n > 0,在这种情况下,我们“ emit n,并对n的递减执行递归1}};或者在n <= 0的情况下,我们终止(所以我们生成一个空列表):

      we w | w > 0 = 0 : te w
           | w == 0 = []
           | otherwise = error "w is less than zero"
          where te n | n > 0 = n : te (n-1)
                     | otherwise = []
      

      就是这样!