2013-02-21 4 views
4

저는 MacroParadise (herehere)와 몇 가지 다른 새로운 기능을 실험 해 왔습니다. TypeTags를 사용하는 동안 유형의 평등을 구현하기 위해 이와 같은 작업을 이제 할 수 있다는 것을 깨달았습니다.스칼라의 매크로를 사용하여 유형 평등을 시행하십시오.

def typeEq[A: TypeTag, B: TypeTag]: Boolean = { 
    implicitly[TypeTag[A]].tpe =:= implicitly[TypeTag[B]].tpe 
} 

나는 다음 TypeTag implicits 컴파일러가 생성되는 것을 기억하고, 내가 이런 식으로보다 간결 TypeTag 사용을 가능하게하는 매크로를 기록 할 수 있습니다 생각했다 :

def foo[A](xs: List[A]): String = xs match { 
    case y :: ys if typeEq[A, String] => y 
    case y :: ys if typeEq[A, Int] => y.toString 
} 

난 단지 작성한을 Lisp에서 매크로를 몇 개 만들었고 매크로 라이브러리를 사용하려고 시도하는 데 걸림돌이되었습니다. 이것은 몇 가지 시도로 나를 이끌지 만 결국 그들은 모두 Int =:= Int과 같이 작동하지 않습니다. 또는 어떤 것도 작동하지 않는 typeA =:= typeB과 같은 것으로 확장됩니다.

이것은 두 가지 질문으로 나를 안내합니다 : 1) 위와 같이 foo의 컨텍스트 경계없이이 작업을 수행 할 수 있습니까? 2) implicits에서 얻은 Type을 결과 표현식에 올바르게 연결하려면 어떻게해야합니까?

매크로와 implicits는 내게 WeakTypeTag 암시 적을 가져오고 그 둘 모두를 컴파일 할 때 발생하기 때문에 tpe 멤버를 스플 라이스에 사용하도록합니다.

답변

3

이미 유형 =:=[From,To]을 사용하여 유형 평등을 적용 할 수 있습니다 :

def bar[A,B](a:A,b:B)(implicit ev: A =:= B)= (a,b) 

bar(1,1) 
res0: (Int, Int) = (1,2) 

bar(1,"3") 

error: could not find implicit value for parameter ev: =:=[Int,java.lang.String] 
     bar(1,"3") 
     ^

편집 :

죄송합니다

, 귀하의 질문에 약간의 잘못을 가지고 같아요. 예제는 거의 작동하지만 컴파일러는 A이 무엇인지 알 수 없기 때문에 TypeTag[A]이라는 증거를 찾을 수 없습니다. 당신이 메서드 정의에 바인딩 컨텍스트를 추가하는 경우가 작동합니다

def foo[A : TypeTag](xs: List[A]) = xs match { 
    case _ if typeEq[A, String] => "yay" 
    case _ => "noes" 
} 

scala> foo(List(2)) 
res0: String = noes 

scala> foo(List("")) 
res1: String = yay 

EDIT2 : 귀하의 예를 들어

실제로 모든, 당신은 단지 패턴 매칭을 사용할 수 있습니다 TypeTag들 필요가 없습니다, 당신은 첫 번째 요소 만 사용할 때 :

def foo[A](xs: List[A]): String = xs match { 
    case (y: String) :: _ => y 
    case y :: _ => y.toString 
} 

scala> foo(List(1,2,3)) 
res6: String = 1 

scala> foo(List("foo")) 
res7: String = foo 

을하지만 패턴 mathcing이 아닌 철저한입니다 thath이 Nil을 처리하지 못하기 때문에,주의하십시오.

+0

두 가지 유형의 동일성을 주장하는 데는 문제가 없지만 = : = 유형의 감시는 지움으로 인해 본문에서 사용할 수 없습니다. foo [Int] 및 foo [String] 호출은 런타임에 동일하므로 삭제 된 정보 (즉, TypeTags)를 복구하기위한 메커니즘이 필요합니다. 필자는 지우는 것과 관계없이 두 유형 간의 형식 평등을 간결하게 설명하는 데 관심이 있습니다. 'typeEq [ty1, ty2]'를'ty1 = : = ty2'로 바꾸면 위의 예제는 컴파일되지 않습니다. 또한 = : =이 실제로는 scala.runtime.reflect.Type'의 메소드가 아니라 클래스 = : =가 아니라 암시 적 감시에 사용된다는 점에 주목할 필요가 있습니다. – jroesch

+0

updated 내 게시물 – drexin

+0

고마워, 그건 내 예제를 해결할 수 있지만 (고작인데). 매크로 작성 부분에 더 관심이 있습니다. 나는 유형을 올바르게 연결하는 데 여전히 문제가있었습니다. 이것은 'A'가'xs.head'의 유형이나 다른 구조와 같지 않을 경우 더 중요합니다. – jroesch