2011-10-26 7 views
8

키와 값이 모두 제네릭 유형 인지도가 있습니다. 이런 식으로 뭔가가 :관련 매개 변수화 된 유형

Map[Foo[A], Bar[A]] 

내가 표현하고 싶은 것은 유형 A지도의 각 키 - 값 쌍에 대한 다를 수 있습니다,하지만 모든 키는 항상 값과 같은 유형의 매개 변수입니다 에 매핑됩니다. 따라서 Foo[Int]은 항상 Bar[Int]에 매핑되고, Foo[String]은 항상 Bar[String]에 매핑됩니다.

누구나 이것을 표현하는 방법을 알고 있습니까?

편집 : 여기

내가 할 노력하고있어 물건의 종류의 예 :

trait Parameter // not important what it actually does 

class Example { 
    val handlers: Map[_ <: Parameter, (_ <: Parameter) => _] = Map() 

    def doSomething() { 
    for ((value, handler) <- handlers) { 
     handler(value) 
    } 
    } 
} 

아이디어는 값은 항상 그것을 받아 들일 수있는 함수에 매핑하는 것입니다 매개 변수로 사용되지만 코드가 작성되므로 컴파일러는이를 알 수 없습니다.

+0

그 라인 자체가 컴파일되지 않습니다. 스칼라는 어딘가에서 그 유형을 선택해야합니다 (클래스 또는 메소드 유형 주석 또는 추상 유형). 암호? –

+0

이것은 http://stackoverflow.com/questions/7401329/map-from-classtto-t-without-casting – michid

답변

2

... 방법을 잘 모르겠어요. 여기에 대략적인 스케치입니다 :

class HMap[A[_], B[_]] extends Iterable[HMap.Mapping[A, B, _]] { 
    private val self = mutable.Map[A[_], B[_]]() 

    def toMapping[T](a: A[_], b: B[_]): HMap.Mapping[A, B, T] = { 
    HMap.Mapping(a.asInstanceOf[A[T]], b.asInstanceOf[B[T]]) 
    } 

    def iterator: Iterator[HMap.Mapping[A, B, _]] = 
    new Iterator[HMap.Mapping[A, B, _]] { 
     val sub = self.iterator 

     def hasNext = sub.hasNext 
     def next(): HMap.Mapping[A, B, _] = { 
     val (key, value) = sub.next() 
     toMapping(key, value) 
     } 
    } 

    def update[T](key: A[T], value: B[T]) = (self(key) = value) 
    def get[T](key: A[T]) = self.get(key).asInstanceOf[Option[B[T]]] 
    def apply[T](key: A[T]) = self(key).asInstanceOf[B[T]] 
} 

object HMap { 
    case class Mapping[A[_], B[_], T](val key: A[T], val value: B[T]) 
} 

이 내부적 대신 맵의 매핑의 링크 된 목록을 사용하여 완전히 형태 보증 할 수 있지만,이 성능이 더 좋다.

내 원래의 예는 다음처럼 보일 것이다 : 나는 경계를 추가하는 방법을 잘 모르겠어요 제외

object Example { 
    type Identity[T] = T 
    type Handler[T] = (T) => _ 

    val handlers = new HMap[Identity, Handler] 

    def doSomething() { 
    for (HMap.Mapping(value, handler) <- handlers) { 
     handler(value) 
    } 
    } 
} 

이 거의 완벽합니다.

1

higher-rank polymorphic 유형의 이질적인지도를 설명하려고합니다.지도의 각 키 - 값 쌍이 다른 유형 매개 변수를 가질 수 있습니다. 스칼라 타입 시스템은 여러분이 이것을 정적으로 표현하는 것을 허용하지 않습니다.

def get [A] (map: Map[Foo[_], Bar[_]], k: Foo[A]) : Bar[A] 
def put [A] (map: Map[Foo[_], Bar[_]], k: Foo[A], v: Bar[A]) 

당신이 좀 더 안전하고 런타임에 각 키 - 값 쌍의 형태 파라미터를 구체화하는 Manifest의를 사용하여 만들 수 있습니다 당신이 할 수있는 최선의 일부 끔찍한, 안전 도우미 메서드를 정의하는 것입니다 생각 그것이 나오는 것에 따라,하지만 난 그게 스칼라에서 이종 맵을 정의 할 수 있습니다,

+0

과 거의 비슷합니다. 안전하지 않은지도를 캡슐화하는 객체의 메소드 여야합니다. 그러면 사용자는 안전한 인터페이스 (또는이 인터페이스를 통해서만 항목을 삽입 할 수있는 안전한 경우도 있지만 너무 제한적 임). 기본 인터페이스에는 매니페스트가 필요하지 않습니다. 구현시 캐스트를 사용해야하지만 실패하지 않도록 할 수 있습니다. – Blaisorblade

-2
scala> trait MyPair { 
    | type T 
    | val key:Foo[T] 
    | val value:Bar[T] 
    | } 
defined trait MyPair 

scala> var l:List[MyPair] = _ 
l: List[MyPair] = null 

scala> l = List(new MyPair{type T = Int; val key = new Foo[Int]{}; val value = new Bar[Int]{} }) 
l: List[MyPair] = List([email protected]) 

scala> l = List(new MyPair{type T = Int; val key = new Foo[Int]{}; val value = new Bar[Int]{} }, new MyPair {type T = String; val key = new Foo[String]{}; val value = new Bar[String]{} }) 
l: List[MyPair] = List([email protected], [email protected]) 

scala> l = List(new MyPair{type T = Int; val key = new Foo[Int]{}; val value = new Bar[Int]{} }, new MyPair {type T = String; val key = new Foo[String]{}; val value = new Bar[Int]{} }) 
<console>:11: error: overriding value value in trait MyPair of type Bar[this.T]; 
value value has incompatible type 
     l = List(new MyPair{type T = Int; val key = new Foo[Int]{}; val value = new Bar[Int]{} }, new MyPair {type T = String; val key = new Foo[String]{}; val value = new Bar[Int]{} }) 
0

원하는대로지도를 구현했습니다.https://github.com/sullivan-/emblem/wiki/TypeBoundMaps

TypeBoundMaps는 하나의 형식 매개 변수를 가지는 형태를 가지고, 그래서 당신은지도에 키와 값 유형에 대한 새로운 유형의 몇 가지를 소개해야합니다 : 당신은 여기에 몇 가지 기본적인 문서를 찾을 수 있습니다

trait Parameter 
type Identity[P <: Parameter] = P 
type Handler[P <: Parameter] = (P) => _ 

trait P1 extends Parameter 
trait P2 extends Parameter 

val p1: P1 = new P1 {} 
val f1: Handler[P1] = { p1: P1 =>() } 

handlers += p1 -> f1 // add a new pair to the map                
val f2: Handler[P1] = handlers(p1) // retrieve a value from the map 
다음은지도를 사용하는 몇 가지 예입니다

var handlers = TypeBoundMap[Parameter, Identity, Handler]() 

:

지금 당신은 당신과 같이 원하는지도를 만들 수 있습니다 6,

지금, 당신의 예에서 for 루프를 모방, 우리는 키 - 값 쌍은 새로운 유형의 TypeBoundPair에 가져다 필요로하는 곳에 매개 변수 값이 일치 :

def handle[P <: Parameter](pair: TypeBoundPair[Parameter, Identity, Handler, P]): Unit = { 
    pair._2(pair._1) 
} 

handlers.foreach { pair => handle(pair) } 

Identity를 도입 뒤에 아이디어 및 Handler 유형에 대한 자세한 내용은 여기를 참조하십시오. http://tinyurl.com/multi-tparam

관련 문제