2017-12-21 19 views
0

암시 적 순서가 정의 된 클래스 (예 : Int, Long, Double) 만 포함 할 수있는 Array (또는 List, ArrayBuffer 등)를 만들고 싶습니다. 이 같은암시 적 순서가있는 스칼라 컬렉션

뭔가 :

val ab = new ArrayBuffer[???]() 
ab += 7 
ab += 8.9 
ab += 8L 

나는 서로 이러한 값을 비교하고 싶지 않아요. 함수에 인수로 전달 될 수 있습니다 범위 Ordering 인스턴스가 유일한 유형을 의미

def createList[T: Ordering](values: T*) = values.toList 

T: Ordering 아래와 같이

+2

당신이 실제로 한 각 유형에 대한 몇 가지'주문 [T]'이 있기 때문에 다른 비교할 수없는 유형의 단일 콜렉션 오브젝트에 넣어 원하는 사실인가요? 예를 들어, 각 구성 요소에 순서가있는 경우 튜플에 대한 순서가 있습니다. 따라서 목록에있는 다른 값과 근본적으로 비교할 수 없다는 가정하에 터플'(1.0, "some string")을'ab'에 추가하는 것이 좋습니다. 그런 'ab'를 나중에 어떻게 사용 하시겠습니까? 어떤 인덱스로'ab'에서 값을 얻을 때 어떤 타입이 될 것으로 예상합니까? – SergGr

+0

필자는 그러한'ab'-s의 배열을 가질 것이고, 예를 들어 모든 것의 첫 번째 값을 비교하기를 원할 것입니다 - 모든 첫 번째 요소가 같은 유형을 갖는다는 것을 인정합니다. –

+0

당신은'HList'를 사용하기를 원할 것입니다. –

답변

1

그냥 유형 클래스 제약 조건을 사용합니다.

scala> def createList[T: Ordering](values: T*) = values.toList 
createList: [T](values: T*)(implicit evidence$1: Ordering[T])List[T] 

scala> case class Cat() 
defined class Cat 

scala> createList(1, 2, 3) 
res2: List[Int] = List(1, 2, 3) 

scala> createList(Cat()) 
<console>:15: error: No implicit Ordering defined for Cat. 
     createList(Cat()) 
      ^

범위에서 정수 정렬이 가능하지만 범위에서 고양이 주문을 사용할 수 없습니다. 당신이 Ordering[Cat]

의 인스턴스를 제공 할 때까지 그래서 당신은 이제 일부 가짜 순서를 제공하고 컴파일러가 인수 의미가 있습니다

scala> implicit val orderingCat: Ordering[Cat] = (a: Cat, b: Cat) => ??? 
orderingCat: Ordering[Cat] = [email protected] 

scala> createList(Cat()) 
res4: List[Cat] = List(Cat()) 

Cat을 허용하면 볼 수 있습니다 Cat 값을 전달할 수 없습니다.

+1

불행히도'Cat'과'Double'을 같은 배열에 저장하고 싶다면 작동하지 않을 것입니다. 예를 들어,'Int'와'String'을 같은 배열에 저장하고 싶다면, 암시적인 Ordering이 정의되어 있지 않은'Any' 인 공통의 슈퍼 타입에 대한 암시적인 순서를 찾을 것입니다. –

+0

@ DánielBerecz 주문이 없으면 주문하십시오. – pamu

0

다른 유형의 객체 목록을 갖고 있고 컴파일 타임에 해당 목록의 객체에 대해 정적으로 계속 확인하려면, shapeless에서 HList과 같은 것을 사용해야합니다. 다음은 두 개의 이기종 목록을 가지고 어떻게 컴파일 타임에 각 목록이 서로 비교 될 수 있는지를 보여주는 예입니다.

import shapeless._ 
import shapeless.ops.hlist.{LiftAll, Zip, Mapper} 

object lt extends Poly1 { 
    implicit def instance[A] = at[(Ordering[A], A, A)] { 
    case (ord, a, b) => ord.lt(a, b) 
    } 
} 

def areLessThan[L <: HList, O <: HList, OLL <: HList](a: L, b: L)(
    implicit 
    ord: LiftAll.Aux[Ordering, L, O], 
    zip: Zip.Aux[O :: L :: L :: HNil, OLL], 
    map: Mapper[lt.type, OLL] 
) = zip(ord.instances :: a :: b :: HNil).map(lt) 

를 사용 :

scala> val a = 1 :: "b" :: Option(4L) :: HNil 
a: Int :: String :: Option[Long] :: shapeless.HNil = 1 :: b :: Some(4) :: HNil 

scala> val b = 2 :: "a" :: Option(7L) :: HNil 
b: Int :: String :: Option[Long] :: shapeless.HNil = 2 :: a :: Some(7) :: HNil 

scala> areLessThan(a, b) 
res10: Boolean :: Boolean :: Boolean :: shapeless.HNil = true :: false :: true :: HNil