2015-01-14 23 views
11

Scala'yı öğreniyorum ve halihazırda mevcut bilgi seviyem için monad kavramının biraz fazla karmaşık olduğunu bulmak zorundaydım. Ancak, amacım en azından for ifadesi ve ek olarak bir filtre ile kullanılabilecek çok basit bir sınıf yapmaktır. anlayış benim açımdanScala: Basit bir özel tipte harita ve withFilter uygulaması

aşağıdaki kurallar geçerlidir:

özel türü için sipariş (jeneratör yalnızca basit değişkenleri üretir) ifadesi için bir jeneratörü kullanılabilir olması için ise
  • , bu ihtiyacı map uygulayın.
  • Ek olarak filtreler kullanılmalıysa, o zaman yazım withFilter'u da uygulamalıdır.

Benim asgari sınıflar şuna benzer: Ancak

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

, beraber örnekler bulmakta zorlanırsanız var: Ben başarmak istiyorum ne

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

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

aşağıdaki yapabilmek olduğunu bu tarz bir sadelik. Çözüm, herhangi bir sınıfa uygulanabilecek genel bir çözüm olmak yerine yukarıda gösterilen iki sınıfa "uyarlanmış" olsaydı sorun olmaz. Bu basit örnek için uygulamanın tersine çevrilmesi kesinlikle bana yardımcı olacaktır. Herhangi bir yardım takdir, teşekkür ederim.

Düzenleme: Lee belirttiği gibi

, benim amacım sadece jenerik türleri için çalışmıyor gibi görünüyor. Sadece sarılı koleksiyona fields üzerine map çağrıyı geçebilir

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

'map' ve' withFilter ', yalnızca' Izgara 've' Alan 'olmayan genel türler için anlamlıdır. Örneğin (f <- grid) için f.name işlevi nasıl çalışır? – Lee

+0

@Lee Cevabınız için teşekkürler, bunun hakkında düşünmek zorundasınız. Düzenlemem bir şeyi değiştiriyor mu? – ceran

cevap

6

Bu durumda: Ben sınıfa Field unutup şöyle Grid yeniden tanımlamak eğer daha mantıklı olur varsayalım.
withFilter için, fields üzerinde filter yöntemini çağırabilirsiniz, ama o withFilter olması gerekiyordu olduğunu semantik doğrultusunda tamamen olmadığını düşünüyorum.

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) 
} 

olurdunuz ne soruyorsun daha doğru, ama dolambaçlı uygulanması: beklendiği gibi

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)) 
    } 
} 

Bu şekilde, withFilterlazily çalışacaktır.

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) 

için-kavrama de-sugaring sözdizimi dayalıdır:

+0

"Düzlem" de flatMap'i kullanmam gerekiyordu (ayrıca flatMap [R] (f: E => Grid [R]): Grid [R] ' – kelloti

2
O Grid bile değil genel tanımıyla çalışacak

henüz map beklediğiniz değil. İfadeyi .map.flatMap.filter vb. Kullanarak yeniden yazar ve sonra da yazım denetimleri (AFAIK).

İlgili konular