你遇到的最好的递归代码是什么?

时间:2014-04-19 07:00:53

标签: recursion functional-programming

由于递归而导致真正复杂的逻辑被简化的情况,在日常编程中使用递归的情况

2 个答案:

答案 0 :(得分:2)

递归的一个惊人的例子是Haskell和相关语言中的定点组合器:

fix f = f (fix f)

允许我们在没有显式递归的情况下编写递归函数

fac = go (fix go) where
    go g 0 = 1
    go g n = n * g (n-1)

虽然它并没有那么有用,因为当然Haskell已经进行了递归。

更重要的是,同样的技巧也适用于类型级别。这是一个模拟文件系统的类型,如目录结构:

data DirEntry a = Dir [(String, a)] | File String
data Fix t = Y (t (Fix t))
type Directory = Fix DirEntry

通过这种方式,我们实际上可以使用类型

的值
DirEntry (DirEntry (DirEntry (DirEntry ...)))  -- nested arbitrarily deep

没有DirectoryDirEntry本身是递归的。

答案 1 :(得分:1)

我最喜欢使用递归是蹦床。这是一种构建可组合代码的方便方法,它不会在没有尾调用消除的语言中溢出调用堆栈。

以下是Rich Dougherty’s blog的一个很好的例子:

sealed trait Bounce[A]
case class Done[A](result: A) extends Bounce[A]
case class Call[A](thunk: () => Bounce[A]) extends Bounce[A]

def even2(n: Int): Bounce[Boolean] = {
  if (n == 0) Done(true)
  else Call(() => odd2(n - 1))
}

def odd2(n: Int): Bounce[Boolean] = {
  if (n == 0) Done(false)
  else Call(() => even2(n - 1))
}

def trampoline[A](bounce: Bounce[A]): A = bounce match {
  case Call(thunk) => trampoline(thunk())
  case Done(x) => x
}

trampoline(even2(9999)) // false

我也强烈推荐RúnarÓli的paper on free monads