scala:函数递归返回一个函数对象,如何克服非法循环引用?

时间:2011-07-03 03:01:55

标签: scala

我有一个带有返回函数对象的方法的类。要求是方法是arity 0并且它的返回类型是Function0的Option - 其返回类型是原始返回类型。例如:

class MyClass {
  def f(): Option[Function[A]] = Some(g _)
  def g(): Option[Function[A]] = Some(h _)
  ... goes on and on, eventually returns Some(z _) ...
  def z(): Option[Function[A]] = None
}

由于递归,问题是类型A被定义为:

type A = Option[Function0[A]]

但由于不允许循环引用,因此会产生错误:

illegal cyclic reference involving type A

我显然想避免为每个方法定义不同的返回类型,但由于循环,似乎不可能使用统一的返回类型。有没有办法做到这一点?谢谢!

2 个答案:

答案 0 :(得分:3)

Scala类型定义不支持此功能。见How to define a cyclic type definition?

您可以使用类而不是类型来完成此操作,但您必须定义自己的类似于类的类。下面是一个例子(省略了monadic方法)。另请参阅此邮件列表讨论:http://www.scala-lang.org/node/2541

sealed trait OptionalFunction extends (() => OptionalFunction) {
  def get: (() => OptionalFunction)
}
case class SomeFunction(fn: () => OptionalFunction) extends OptionalFunction {
  def apply() = fn()
  def get = fn
}
case object NoFunction extends OptionalFunction {
  def apply() = this
  def get = throw new NoSuchElementException
}

class MyClass {
  type A = OptionalFunction
  def f(): A = SomeFunction(g _)
  def g(): A = SomeFunction(h _)
  def h(): A = SomeFunction(() => { println("At the end!"); i })
  def i(): A = NoFunction
}

scala> new MyClass().f()()()()
At the end!
res0: OptionalFunction[Unit] = <function0>

答案 1 :(得分:0)

我不确定这是否是你正在寻找的东西,但是许多这些边缘情况可以通过显式使用对象来解决:

abstract class F extends Function0[F]
val p = new F {
    def apply() = { println("hi"); this }
}
>> defined class F
>> p: $anon forSome { type $anon <: F{def apply(): $anon} } =     
p()    
>> hi
>> res2: $anon =     
p()()    
>> hi
>> hi
>> res3: $anon = 

快乐的编码。