Scala 从';数据类型按顺序';在斯卡拉

Scala 从';数据类型按顺序';在斯卡拉,scala,scalaz,Scala,Scalaz,我正试图从Scala中编写foldTerm函数。这是我到目前为止得到的 def foldTerm[F[+_], A, B](e: Free[F, A], pure: A ⇒ B, imp: F[B] ⇒ B)(implicit F: Functor[F]): B = e.resume match { case Right(a) ⇒ pure(a) case Left(x) ⇒ imp(F.map(x)(foldTerm(_, pure, imp))) } 这是可行的,但

我正试图从Scala中编写
foldTerm
函数。这是我到目前为止得到的

def foldTerm[F[+_], A, B](e: Free[F, A], pure: A ⇒ B, imp: F[B] ⇒ B)(implicit F: Functor[F]): B =
  e.resume match { 
    case Right(a) ⇒ pure(a)
    case Left(x)  ⇒ imp(F.map(x)(foldTerm(_, pure, imp)))
}
这是可行的,但由于Scala无法正确优化尾部递归,因此会导致SOE。我试着用蹦床来修复它,但到目前为止还没有任何运气。我觉得我应该能够用
Free
上的现有方法来实现这一点,但我所有的尝试都以失败告终


我缺少什么?

Scala可以正确地消除尾部递归调用。但是您的方法不是尾部递归的。您可以使用
@annotation.tailrec
注释进行检查

@annotation.tailrec
def foldTerm[F[+_], A, B](e: Free[F, A], pure: A ⇒ B, imp: F[B] ⇒ B)(implicit F: Functor[F]): B =
  e.resume match { 
    case Right(a) ⇒ pure(a)
    case Left(x)  ⇒ imp(F.map(x)(foldTerm(_, pure, imp)))
}

<console>:19: error: could not optimize @tailrec annotated method foldTerm: it contains a recursive call not in tail position
           case Left(x)  ⇒ imp(F.map(x)(foldTerm(_, pure, imp)))
@annotation.tailrec
def foldTerm[F[+],A,B](e:Free[F,A],pure:A⇒ B、 imp:F[B]⇒ B) (隐式F:函子[F]):B=
e、 恢复匹配{
案例权利(a)⇒ 纯(a)
案例左(x)⇒ imp(F.map(x)(foldTerm,pure,imp)))
}
:19:错误:无法优化@tailrec带注释的方法foldTerm:它包含一个不在尾部位置的递归调用
案例左(x)⇒ imp(F.map(x)(foldTerm,pure,imp)))

你最后一次打电话是
imp
,而不是
foldTerm

,结果证明这毕竟不是我的问题。我在一个大的列表上使用了一个
ListT.fromList
,这就是导致堆栈崩溃的原因。切换到使用
StreamT
解决了这个问题。

那么为什么他说scala不能消除尾部递归调用?因为scala只应用了一个递归优化:尾部调用位置。由于它的惰性,Haskell可以处理更多的递归优化。我知道,您可能对此感兴趣,但OP说“Scala无法正确优化尾部递归”,这是不对的。这就是我回答的原因。正如你所说,Scala只能优化最简单的尾部调用。它不能优化相互递归的函数。