제네릭 기반의 오버로딩 메서드

Aug 29 2020

제네릭을 기반으로 메서드를 오버로드하고 싶습니다.

case class Indexed2dArr[Dim0Type, Dim1Type] (
  indices: (List[Dim0Type], List[Dim1Type]),
  array: List[List[Float]],
) {
  def getSliceAtIndexLocation(i: Dim0Type): (List[Dim1Type], List[Float]) = ???
  def getSliceAtIndexLocation(i: Dim1Type): (List[Dim0Type], List[Float]) = ???
}

따라서를 getSliceAtIndexLocation매개 변수로 호출 Dim0Type하면 원래 배열의 단일 차원 슬라이스를 인덱스로 반환합니다 Dim1Type. 를 사용하여 호출하는 경우도 마찬가지입니다 Dim1Type.

이로 인해 double definition컴파일러 오류가 발생합니다.이 두 메서드는 유형 삭제 후 동일한 유형을 가지며이 유형은 (i: Object): Tuple2. 이것을 엉망으로 만드는 유효한 방법이 있습니까? 아니면 똑바로 불가능합니까?

답변

3 DmytroMitin Aug 29 2020 at 15:34

둘 중 하나를 시도 DummyImplicit

case class Indexed2dArr[Dim0Type, Dim1Type] (
  indices: (List[Dim0Type], List[Dim1Type]),
  array: List[List[Float]],
) {
  def getSliceAtIndexLocation(i: Dim0Type): (List[Dim1Type], List[Float]) = ???
  def getSliceAtIndexLocation(i: Dim1Type)(implicit 
    di: DummyImplicit): (List[Dim0Type], List[Float]) = ???
}

또는 유형 클래스 패턴

case class Indexed2dArr[Dim0Type, Dim1Type] (
  indices: (List[Dim0Type], List[Dim1Type]),
  array: List[List[Float]],
) {
  def getSliceAtIndexLocation[A](i: A)(implicit tc: TC[A]): tc.Out = tc(i)

  trait TC[A] {
    type B
    type Out = TC.MkOut[B]
    def apply(i: A): Out
  }
  object TC {
    type MkOut[B] = (List[B], List[Float])

    type Aux[A, B0] = TC[A] { type B = B0 }
    def instance[A, B0](f: A => MkOut[B0]): Aux[A, B0] = new TC[A] {
      override type B = B0
      override def apply(i: A): Out = f(i)
    }
  
    implicit val dim0Type: Aux[Dim0Type, Dim1Type] = instance(i => ???)
    implicit val dim1Type: Aux[Dim1Type, Dim0Type] = instance(i => ???)
  }
}

또는 자석 패턴

import scala.language.implicitConversions

case class Indexed2dArr[Dim0Type, Dim1Type] (
  indices: (List[Dim0Type], List[Dim1Type]),
  array: List[List[Float]],
) {
  def getSliceAtIndexLocation(m: Magnet): m.Out = m()

  trait Magnet {
    type B
    type Out = Magnet.MkOut[B]
    def apply(): Out
  }
  object Magnet {
    type MkOut[B] = (List[B], List[Float])

    type Aux[B0] = Magnet { type B = B0 }
    def instance[B0](x: MkOut[B0]): Aux[B0] = new Magnet {
      override type B = B0
      override def apply(): Out = x
    }

    implicit def dim0Type(i: Dim0Type): Aux[Dim1Type] = instance(???)
    implicit def dim1Type(i: Dim1Type): Aux[Dim0Type] = instance(???)
  }
}