haskell - 在递归调用中向后传播信息

标签 haskell recursion

如何在递归调用链中向后传播信息?

例如:

f :: [Int] -> [Int]
f (x:xs)
  | x `mod` 17 = ...
  | otherwise = (x + 1) : f xs
f [] = []

我想在...停止评估,并且我还想将该信息传播回调用者(它停止的事实)。我尝试使用像 Maybe 这样的返回类型,但随后我必须对递归调用进行模式匹配,从而失去尾部调用优化,因为我必须在调用返回后对其进行评估(注意:可以轻松地将上面的代码转换为TR 形式,但我这样保留是为了更容易理解)。

您能否提出一个仍能从 TCO 中受益的更好解决方案?

最佳答案

您始终可以使用额外的参数,并返回一个包含累积结果的元组。这样您仍然可以从 TCO 中受益,并获得所需的信息。

一个例子:

f :: [Int] -> Bool -> [Int] -> (Bool, [Int])
f (x:xs) l accum
  | x `mod` 17 == 0 = (False, accum)
  | otherwise       = f xs l ((x+1) : accum)
f [] l accum = (True, accum)

或者以更优雅的方式:

data CheckedValue a = Valid a | Invalid a
  deriving Show

f :: [Int] -> [Int] -> CheckedValue [Int]
f (x:xs) accum
  | x `mod` 17 == 0 = Invalid accum
  | otherwise       = f xs ((x+1) : accum)
f [] accum = Valid accum

注意:这些函数也会反转列表,但不必注意这一点。

关于haskell - 在递归调用中向后传播信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42569216/

相关文章:

haskell - 如何声明 newtype 语句中的类型变量属于某个类型类的类型?

haskell - 如何使用可扩展效果和IO?

java - 通过递归打印你可以爬楼梯的总数

linux - 如何递归查找并列出具有子目录和时间的目录中的最新修改文件

c++ - 使用递归后程序爆炸

function - Haskell - lambda 表达式

haskell - 进行字段数据类型操作的最佳方法是什么?

haskell - 了解 Haskell 中的结构共享

recursion - SICP 中练习 1.6 的解释是什么?

java - findMin 惰性删除二叉搜索树