2016-09-09 6 views
9

나는, 나는이 같은 집계의 몇 가지있다이이 스칼라 코드가 유추하지 않는 이유는 무엇입니까?

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

    def show: K 
} 

과 같은 몇 가지 코드와 통합 프레임 워크를 구축하고

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

    def show = value 
} 

내가 같이하는 집계를 정의하면

,

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

다음과 같이 쓸 수 없습니다.

4,대신 나는, 나는 그것을 달성하기 위해 깨끗한 방법이 그 유형을 지정 싫어 자사가 Long 부분을 파악하지 이후이

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

를 작성했다?

답변

4

트릭 내가 배운 :

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] 정제 어떻게 든 유형 밖으로 컴파일러 그림을하는 데 도움이됩니다.

+0

와우, 멋지게 작동합니다. –

+0

값은 기술적으로 [복합 유형] (http://docs.scala-lang.org/tutorials/tour/compound-types)입니다. –

+0

이상적으로 말하면,'T'는'Aggregate [T, K]'를 확장한다고 말했기 때문에 필요하지 않습니다. 내가 볼 수없는 통일 알고리즘의 기술적 한계가있을 수 있습니다. –

4

MonoidShow 유형 클래스를 사용하는 것이 좋습니다. 새끼 고양이를 사용하기를 원할 수도 있습니다. 사례 링크를 위해 MonoidShow 인스턴스를 자동으로 파생 시키려면 새 링크 (예 : Google의 "scala kittens derivation"만 추가하십시오.

+0

이 패턴에 익숙하지 않은 분은 http://tpolecat.github.io/2013/10/12/typeclass.html – tpolecat

+0

감사합니다. Paul, 현재 직면 한 주요 문제는 제가 원합니다. 이 세미 그룹을 키 값 저장소로 직렬화하고 컴파일 할 때 세미 그룹 인스턴스를 알 수 없습니다. 따라서 semigroup 자체가 다형성을 가지며 이진 연산을 갖기를 원한다. (나는 Semigroup을 타입 클래스와 달리 유지해야한다.) –

관련 문제