Haskell无尾递归

Haskell无尾递归,haskell,Haskell,我想知道这是否表示尾部递归。如果不是,我该怎么做 countP :: [a] -> (a->Bool) -> Int countP [] _ = 0 countP (x:xs) p = countP_aux (x:xs) p 0 countP_aux [] _ _ = 0 countP_aux (x:xs) p acumul |p x==True = (countP_aux xs p (acumul))+1

我想知道这是否表示尾部递归。如果不是,我该怎么做

 countP :: [a] -> (a->Bool) -> Int
 countP [] _ = 0
 countP (x:xs) p = countP_aux (x:xs) p 0

 countP_aux [] _ _ = 0
 countP_aux (x:xs) p acumul
                        |p x==True = (countP_aux xs p (acumul))+1
                        |otherwise = (countP_aux xs p (acumul))

  countP [1,2,3] (>0)
  3
  (72 reductions, 95 cells)
此练习显示列表中有多少值通过p条件验证。
谢谢

这不是尾部递归,因为

(countP_aux xs p (acumul))+1
尾部调用应该返回递归调用的结果,而不是使用递归调用的结果进行计算

您可以使用累加器将非尾部递归函数转换为尾部递归函数,在累加器中执行附加工作,即

假设你有一个简单的计数功能

f a
  | a < 1 = 0 
  | otherwise = f (a-1) + 1
您可以将其设置为尾部递归,如下所示:

f' acc a = 
  | a < 1 = acc 
  | otherwise = f' (acc + 1) (a-1)
f = f' 0

这不是尾部递归,因为

(countP_aux xs p (acumul))+1
尾部调用应该返回递归调用的结果,而不是使用递归调用的结果进行计算

您可以使用累加器将非尾部递归函数转换为尾部递归函数,在累加器中执行附加工作,即

假设你有一个简单的计数功能

f a
  | a < 1 = 0 
  | otherwise = f (a-1) + 1
您可以将其设置为尾部递归,如下所示:

f' acc a = 
  | a < 1 = acc 
  | otherwise = f' (acc + 1) (a-1)
f = f' 0


我遇到了双重否定的问题-如果它不是一个非尾部递归意味着什么?顺便说一句,我认为countP[]f应该总是返回0。你的代码失败了。我想知道它是否代表尾部递归。Post Edited如果它是尾部递归为什么重要?尾部递归比非尾部递归有更好的性能recursion@tomss不存在惰性评估。尾部递归在严格的语言中更快,但Haskell是非严格的。你应该读一读,我遇到了双重否定的问题——如果它不是无尾递归,意味着什么?顺便说一句,我认为countP[]f应该总是返回0。你的代码失败了。我想知道它是否代表尾部递归。Post Edited如果它是尾部递归为什么重要?尾部递归比非尾部递归有更好的性能recursion@tomss不存在惰性评估。尾部递归在严格的语言中更快,但Haskell是非严格的。你应该读书,我怎么做?谢谢。重构到f'acc a然后让f=f'0可能会很好,对累加器进行排序也可能会很好……因为这样你就不会建立一大堆未评估的thunks。ghc可能自己就能解决这个问题,不是吗?给定的东西是尾部递归的,懒惰累加器的问题是其他的。我该怎么做呢?谢谢。重构到f'acc a然后让f=f'0可能会很好,对累加器进行排序也可能会很好……因为这样你就不会建立一大堆未评估的thunks。ghc可能自己就能解决这个问题,不是吗?给定的东西是尾部递归的,惰性累加器的问题是其他的。