2016-09-09 16 views
9

buduję ramy agregacji z kodem, który wygląda takDlaczego ten kod scala nie wnioskuje o typie?

trait Aggregate[T <: Aggregate[T, K], K] { self: T => 
    def plus(another: T): T 

    def show: K 
} 

mam kilka skupisk takich jak ta,

case class Count(value: Long = 1) extends Aggregate[Count, Long] { 
    def plus(another: Count) = Count(value + another.value) 

    def show = value 
} 

Raz zdefiniować agregację który jest podobny do tego,

case class By[T <: Aggregate[T, K], K, G](values: HashMap[G, T]) extends Aggregate[By[T, K, G], Map[G, K]] { 
    override def plus(another: By[T, K, G]): By[T, K, G] = By(values.merged(another.values){case ((k1,v1), (k2,v2)) => (k1, v1 plus v2)}) 

    override def show: Map[G, K] = values.map{case (k,v) => k -> v.show} 
} 

object By { 
    def apply[T <: Aggregate[T,K], K, G](key:G, value:T):By[T, K, G] = By(HashMap(key -> value)) 
} 

Nie mogę napisać coś takiego

By("key1", Count(100)) 

Zamiast tego musiałem napisać ten

By[Count, Long, String]("key1", Count(100)) 

ponieważ jego nie zastanawianie się Long część, nienawidzę, aby określić te typy, czy jest bardziej przejrzysty sposób to osiągnąć?

Odpowiedz

4

Sztuczka Dowiedziałem:

object By { 
    def apply[T <: Aggregate[T,K], K, G](key:G, value:T with Aggregate[T,K]):By[T, K, G] = By(HashMap(key -> value)) 
} 

with Aggregate[T,K] wyrafinowanie jakoś pomaga postać kompilatora out typów.

+0

Wow, zadziwia, działa jak urok. –

+0

wartość jest technicznie [typem złożonym] (http://docs.scala-lang.org/tutorials/tour/compound-types). –

+0

Idealnie nie powinien tego potrzebować, ponieważ powiedziałem "T" przedłużyć 'Aggregate [T, K]'. Może być jakieś techniczne ograniczenie w algorytmie unifikacji, którego nie jestem w stanie zobaczyć. –

4

Proponuję użyć klas typu Monoid i Show. Możesz nawet użyć kociąt (przepraszam, nie mam wystarczającej liczby przedstawicieli, aby dodać kolejny link, po prostu Google "wyprowadzenie kotów scala"), aby automatycznie wyprowadzać instancje Monoid i Show dla klas spraw.

+0

Jeśli nie znasz tego wzorca, to działa przykład http://tpolecat.github.io/2013/10/12/typeclass.html – tpolecat

+0

Dzięki Paul, Głównym problemem, z którym teraz borykam jest to, że chcę serializować te półgrupy do magazynu wartości kluczy, a ja nie wiem, co to jest półgrupa w chwili kompilacji. Tak więc chciał, aby sama półgrupa była polimorficzna i miała operację binarną (być może będę musiał utrzy- mywać półgrupę typograficzną wraz z nią inaczej). –

Powiązane problemy