2016-01-22 75 views
0

給定一個包含某些「類型」標籤的對象。 根據某些標準設計匹配器的實現的最佳方式是什麼?問題的關鍵在於如何有效地利用類型系統。如何根據Scala中的標籤過濾標準

這是我目前的嘗試:

object Criteria1 extends App { 

    // Features 
    // Feature A 
    trait A 
    case object A1 extends A 
    case object A2 extends A 

    // Feature B 
    trait B 
    case object B1 extends B 
    case object B2 extends B 

    // Criteria 
    trait Criteria 
    case class ACriteria(a: Set[A]) extends Criteria 
    case class BCriteria(b: Set[B]) extends Criteria 

    // Tag 
    trait Tag 
    case class ATag(a: A) extends Tag 
    case class BTag(b: B) extends Tag 


    def match_?(criterias: Set[Criteria], tags: Set[Tag]) : Boolean = { 
    !criterias.exists { 
     case ACriteria(v) => !v.map(value => ATag(value)).exists(tags.contains) 
     case BCriteria(v) => !v.map(value => BTag(value)).exists(tags.contains) 
    } 
    } 

    println(match_?(Set(ACriteria(Set(A1, A2))), Set(ATag(A1), ATag(A2)))) // true 
    println(match_?(Set(ACriteria(Set(A1))), Set(ATag(A1), ATag(A2)))) // true 
    println(match_?(Set(ACriteria(Set(A1, A2))), Set(ATag(A1)))) // true 
    println(match_?(Set(), Set(ATag(A1)))) // true 
    println(match_?(Set(ACriteria(Set(A1))), Set())) // false 
    println(match_?(Set(ACriteria(Set(A1)), BCriteria(Set(B1))), Set(ATag(A1)))) // false 
    println(match_?(Set(ACriteria(Set(A1)), BCriteria(Set(B1))), Set(BTag(B1)))) // false 

} 

但它冗長,在比賽中沒有方法真幹代碼。

[更新]當我想起來,似乎CriteriaTags類型不是很有用。這是一個更簡單的版本,但是由於Any也有較低的類型檢查。任何方式來解決(也許Coproduct)?

object Criteria6 extends App { 

    // Features 
    // Feature A 
    trait A 
    case object A1 extends A 
    case object A2 extends A 

    // Feature B 
    trait B 
    case object B1 extends B 
    case object B2 extends B 

    def match_?(criterias: Set[Set[Any]], tags: Set[Any]) : Boolean = { 
    !criterias.exists { 
     v => !v.exists(tags.contains) 
    } 
    } 

    println(match_?(Set(Set(A1, A2)), Set(A1, A2))) // true 
    println(match_?(Set(Set(A1)), Set(A1, A2))) // true 
    println(match_?(Set(Set(A1, A2)), Set(A1))) // true 
    println(match_?(Set(), Set(A1))) // true 
    println(match_?(Set(Set(A1)), Set())) // false 
    println(match_?(Set(Set(A1), Set(B1)), Set(A1))) // false 
    println(match_?(Set(Set(A1), Set(B1)), Set(B1))) // false 
} 
+0

不知道我理解你正試圖在這裏完成的。鑑於你有什麼,我會用類型參數替換標準和標籤實例。假設,'case class Tag [T](t:T)'。 –

回答

0

因此Type parameters似乎是你想要的。

object Criteria6 extends App { 

    // Features 
    // Feature A 
    trait A 
    case object A1 extends A 
    case object A2 extends A 

    // Feature B 
    trait B 
    case object B1 extends B 
    case object B2 extends B 

    def match_?[T](criterias: Set[Set[T]], tags: Set[T]) : Boolean = { 
    !criterias.exists { 
     v => !v.exists(tags.contains) 
    } 
    } 

    println(match_?(Set(Set(A1, A2)), Set(A1, A2))) // true 
    println(match_?(Set(Set(A1)), Set(A1, A2))) // true 
    println(match_?(Set(Set(A1, A2)), Set(A1))) // true 
    println(match_?(Set(), Set(A1))) // true 
    println(match_?(Set(Set(A1)), Set())) // false 
    println(match_?(Set(Set(A1), Set(B1)), Set(A1))) // false 
    println(match_?(Set(Set(A1), Set(B1)), Set(B1))) // false 
} 

這將有額外的好處,你將無法調用match_?不匹配的類型(A或B)。

我還是不明白是什麼是Set(Set(A1, A2)), Set(A1, A2))應該代表需要驗證...