12

假设我有一个像这样的愚蠢的小案例类:

case class Foo(name: String, other: Foo)

我怎样才能定义ab不可变的那样a.otherisbb.otheris a?scala 是否提供了一些“打结”的方法?我想做这样的事情:

val (a, b): (Foo, Foo) = (Foo("a", b), Foo("b", a)) // Doesn't work.

可能性

在 Haskell 中,我会这样做:

data Foo = Foo { name :: String, other :: Foo }

a = Foo "a" b
b = Foo "b" a

a与和的绑定b包含在同一个let表达式中,或者在顶层。

或者,在不滥用 Haskell 的自动 letrec 功能的情况下:

(a, b) = fix (\ ~(a', b') -> Foo "a" b', Foo "b" a')

注意惰性模式,~(a', b')这很重要。

4

1 回答 1

15

您希望Foo保持不变,但 Scala 中的懒惰在声明站点上。不改变它就不可能Foo是非严格的,并且 Haskell 中指示的模式仅有效Foo,因为那里是非严格的(即Foo "a" bb立即评估)。

否则解决方案几乎相同,允许使所有内容变得非严格:

class Foo(name: String, other0: => Foo) { // Cannot be case class, because that mandates strictness
  lazy val other = other0 // otherwise Scala will always reevaluate
}
object Foo {
  def apply(name: String, other: => Foo) = new Foo(name, other)
}

val (a: Foo, b: Foo) = (Foo("a", b), Foo("b", a))
于 2012-06-06T03:12:57.987 回答