2015-01-14 10 views
11

私はScalaを学んでおり、モナドの概念は現在の知識レベルでは洗練されていないことがわかりました。しかし、私の目標は、少なくともfor式で使用できる非常に単純なクラスを作成し、さらにフィルタを作成することです。Scala:単純なカスタムタイプのmapとwithFilterの実装

理解の私の観点から、以下のルールが適用されます。

  • 発現させるための発電機で使用できるようにするカスタムタイプのためには、(発電機のみの単純な変数を生成している)、それはする必要がありますmapを実装します。
  • フィルターをさらに使用する必要がある場合は、タイプもwithFilterを実装する必要があります。

私の最小限のクラスは次のようになります。しかし、私はと例を見つけるのに苦労してい

for(f <- grid) yield f.name // needs map 
for(f <- grid; if f.isVisisble) yield f.name // needs map + withFilter 

class Grid(private val fields: IndexedSeq[Field]) 

class Field(val name: String, val isVisible: Boolean) 

私が達成したい何が次の操作を行うことができていますそんなシンプルさ。ソリューションが、どのクラスにも適用可能な一般的なソリューションではなく、上の2つのクラスに合わせて調整されていれば問題ありません。この単純な例の実装を理解することは間違いなく私を助けます。どんな助けもありがとう、ありがとう。

編集:李氏は指摘したように

、私の意図は、一般的なタイプのために働くように見えます。あなただけのラップコレクションfieldsの上mapコールを渡すことができ

class Grid[E](private val fields: IndexedSeq[E]) 
+3

'map'と' withFilter'は、 'Grid'と' Field'はそうではないジェネリック型に対してのみ意味があります。 for(f < - grid)yield f.name'はどのように動作しますか? – Lee

+0

@リあなたのお返事ありがとうございます、それについて考える必要があります。私の編集は何か変わるのですか? – ceran

答えて

6

をこの場合:私は、私はクラスFieldを忘れると、次のようにGridを再定義する場合、それはより多くの意味になるだろうと仮定します。
withFilterについてはfieldsfilterメソッドを呼び出すことができますが、それはwithFilterが持つはずのセマンティクスと完全に一致していないと思います。あなたが求めているものの

case class Grid[E](private val fields: IndexedSeq[E]) { 
    def map[R](f: E => R): Grid[R] = new Grid(fields map f) 
    def withFilter(p: E => Boolean): Grid[E] = new Grid(fields filter p) 
} 

より正しいが、複雑な実装は次のようになります。

case class Grid[E](private val fields: IndexedSeq[E]) { 
    def map[R](f: E => R): Grid[R] = new Grid(fields map f) 
    def withFilter(p: E => Boolean): WithFilter = new WithFilter(p) 

    class WithFilter(p: E => Boolean) { 
    def map[R](f: E => R): Grid[R] = new Grid(fields.withFilter(p).map(f)) 
    def withFilter(q: E => Boolean): WithFilter = new WithFilter(x => p(x) && q(x)) 
    } 
} 

そのように予想されるように、withFilterlazilyに動作します。

+0

'flatMap'を' WithFilter'に実装する必要もありました( 'def flatMap [R](f:E => Grid [R]):Grid [R]') – kelloti

2

それはGridのさえない一般的な定義では動作しますが、まだmapは、あなたが期待するものではありません。

case class Field(name: String, isVisible: Boolean) 

case class Grid(val fields: IndexedSeq[Field]) { 
    def map[B](f: Field => B): IndexedSeq[B] = 
    fields.map(f) 

    def filter(f: Field => Boolean): Grid = 
    new Grid(fields.filter(f)) 
} 

val grid = new Grid(Vector(Field("foo", true), Field("bar", false))) 

// works 
for { f <- grid } yield f.name 
// res7: IndexedSeq[String] = Vector(foo, bar) 

for { f <- grid; if f.isVisible } yield f.name 
// res13: IndexedSeq[String] = Vector(foo) 

については、理解ドsugaringは構文ベースです。 .map.flatMap.filterなどを使用して式を書き換えてから、型チェック(AFAIK)を実行します。

関連する問題