2

値を遅延格納するだけの単純なクラス flatMap/map :

[注 1: このクラスは、flatMap/map を持つ任意のクラスに置き換えることができます。オプションは具体的な例の 1 つにすぎません。この質問は一般的なケースに関するものです]

[注 2: scalaz は興味深いライブラリですが、この質問はそれに関するものではありません。以下に投稿したもの以外に std scala ライブラリ ソリューションがない場合は、それで問題ありません。]

class C[A](value : => A) {
   def flatMap[B](f: A => C[B]) : C[B] = { f(value) }
   def map[B](f: A => B) : C[B] = { new C(f(value)) }
   override def toString = s"C($value)"
}
object C {
   def apply[A](value : => A) = new C[A](value)
}

flatMap をメンバーに繰り返し適用する関数:

def invert[A](xs: Traversable[C[A]], acc: List[A] = Nil) : C[List[A]] =
  if(xs.nonEmpty) {
    xs.head flatMap { a => invert(xs.tail, a :: acc) }
  } else {
    C(acc.reverse)
  }

実際の機能:

scala> val l = List(C(1),C(2),C(3))
l: List[C[Int]] = List(C(1), C(2), C(3))

scala> invert(l)
res4: C[List[Int]] = C(List(1, 2, 3))     

「反転」を慣用的に書き直す方法はありますか? また、ここで行っていることを表す機能的な「動詞」はありますか?

4

2 に答える 2

1

ソリューションの問題は、完全に(末尾だけでなく)再帰的であるため、大きなリストに対してスタックオーバーフローが発生することです。代わりに折ります:

def invert[A](xs: Traversable[C[A]]) =
  (C(List[A]()) /: xs){ (c,x) => c.flatMap(l => x.map(_ :: l)) }.map(_.reverse)
于 2013-02-19T15:49:37.560 に答える
0

invertパターン マッチを使用すると少しわかりやすくなるかもしれませんが、基本的には同じコードです。

xs match {
  case x0 :: xMore => x0.flatMap(a => invert(xMore, a :: acc))
  case Nil => C(acc.reverse)
}
于 2013-02-19T15:31:22.143 に答える