1

質問

エラーの原因を理解するための支援が必要です。オリジナルはCoursera Scala Design Functional Random Generatorsからのものです。

仕事

random int および random boolean のファクトリを使用して、ランダム ツリー ファクトリを実装しようとしています。

trait Factory[+T] {
self => // alias of 'this'
    def generate: T
    def map[S](f: T => S): Factory[S] = new Factory[S] { 
        def generate = f(self.generate) 
    }
    def flatMap[S](f: T => Factory[S]): Factory[S] = new Factory[S] { 
        def generate = f(self.generate).generate 
    }
}
val intFactory = new Factory[Int] {
    val rand = new java.util.Random
    def generate = rand.nextInt()
}
val boolFactory = intFactory.map(i => i > 0)

問題

1 番目のブロックで実装するとエラーが発生しますが、2 番目のブロックに変更するとエラーは発生しません。Factory[+T]私はそれを意味するFactory[Inner]と信じておりFactory[Leaf]、両方ともとして扱われる可能性がありますFactory[Tree]

for ブロックの同じ if 式がOKであるのに、yieldブロックではOKではない理由がわかりません。説明に感謝します。

trait Tree
case class Inner(left: Tree, right: Tree) extends Tree
case class Leaf(x: Int) extends Tree

def leafFactory: Factory[Leaf] = intFactory.map(i => new Leaf(i))
def innerFactory: Factory[Inner] = new Factory[Inner] {
  def generate = new Inner(treeFactory.generate, treeFactory.generate)
}

def treeFactory: Factory[Tree] = for {
  isLeaf <- boolFactory
} yield if (isLeaf) leafFactory else innerFactory
                    ^^^^^^^^^^^      ^^^^^^^^^^^^
                    type mismatch; found : Factory[Inner] required: Tree
                    type mismatch; found : Factory[Leaf]  required: Tree    

ただし、以下は機能します。

def treeFactory: Factory[Tree] = for {
  isLeaf <- boolFactory
  tree   <- if (isLeaf) leafFactory else innerFactory
} yield tree
4

1 に答える 1

2

for ブロックの同じ if 式は問題ないのに、yield ブロックでは問題ない理由がわかりません

コンパイラによって異なる方法で変換されるためです。前の例は次のように翻訳されます。

boolFactory.flatMap((isLeaf: Boolean) => if (isLeaf) leafFactory else innerFactor)

これは期待される を生成Factory[Tree]し、後者は次のように変換されます:

boolFactory.map((isLeaf: Boolean) => if (isLeaf) leafFactory else innerFactory)

Factory[Factory[Tree]]ではなくを生成するFactory[Tree]ため、メソッドのシグネチャに準拠していません。これは共分散に関するものではなく、理解のためにこれらのステートメントをどのように異なる方法で変換するかということです。

于 2016-08-23T06:58:18.760 に答える