2010-06-26 2 views
11

저는 스칼라 2.8을 재미있게 사용하여 pimp을 정의하려고 시도했으며 형식 생성자에 "as"메소드를 추가하여 한 펑터에서 다른 펑터로 변환 할 수있었습니다 (나는 여기서 반드시 펑터를 다루지 않는다는 사실을 간과 해주십시오). 그래서 예를 들어, 당신은이처럼 사용할 수 있습니다 그래서 여기"실재 상으로는 매개 변수화 된 유형을 추상화 할 수 없습니다 ..."

val array:Array[T] 
val list:List[T] = array.as[List] 

을거야 내가하려고 무엇을 : naturalTransformations의 정의 오류 "할 수 실존 추상적 인하지로 플래그가 있지만

object Test { 
    abstract class NatTrans[F[_], G[_]] { 
     def convert[T](f:F[T]):G[T] 
    } 

    implicit def array2List:NatTrans[Array, List] = new NatTrans[Array, List] { 
     def convert[T](a:Array[T]) = a.toList 
    } 

    // this next part gets flagged with an error 
    implicit def naturalTransformations[T, F[_]](f:F[T]) = new { 
     def as[G[_]](implicit n:NatTrans[F, G]) = n convert f 
    } 
} 

매개 변수화 된 유형 G [T] " 이상.

class Transformable[T, F[_]](f:F[T]) { 
    def as[G[_]](implicit n:NatTrans[F, G]) = n convert f 
} 

implicit def naturalTransformations[T, F[_]](f:F[T]) = new Transformable[T, F](f) 

을하며 일을 나타납니다 :이 문제를 해결하려면, 그래서 같은 추가 클래스 Transformable와 함께 naturalTransformations를 다시 작성할 수 있습니다. 그러나 그것은 나의 첫번째 시도가 동등한 것 같아야하는 것처럼 보인다. 그래서 나는 그것이 실패한 이유와 오류 메시지가 의미하는 것이 궁금하다.

+1

유사한 상황에서 구조 미세 조정의 매개 변수 유형이 해당 상세 조정 외부에 정의 된 추상 유형을 참조하지 않을 수 있다는 오류를 보는 데 익숙합니다. 이 제한은 JVM에서 리플렉션 IIRC를 사용하여 구조 유형을 구현하는 방식과 관련이 있습니다. http://stackoverflow.com/questions/2685804/scala-parameter-type-in-structural-refinement-may-not-refer-to-an-abstract-type – retronym

답변

10

내 직감이 때문에 인해 사양에 다음과 같은 문장, § 6.11, 블록 인 것이 될 것이다 :

T가 존재 절 타입 t에 의해 바인딩 =

로컬로 정의 된 유형 정의 타입 t > : T < : T. t가 형식 매개 변수를 전달하면 오류입니다.

그리고 구조적 인스턴스 생성 식은 블록 평가되므로


new {def greet{println("hello")}} 

는 (의 § 6.10에 따라 그 블록 식으로 계산하므로


{ class anon$X extends AnyRef{ def greet = println("hello") }; new anon$X } 

대한 속기 사양), 전술 한 제한과 함께. 그러나 왜 이런 제한이 있는지 나는 모른다. Throw 된 오류는 Typers 클래스 this location에서 확인할 수 있습니다. 이는이 제한 사항이 사용자가 보는 오류의 원인임을 확인하는 것으로 보입니다. 이 일반성 케이스에 대한 단순 같은 소리 나에게


scala> class N[M[_]] 
defined class N 

scala> class Q { def as[M[_]](n:N[M]) = null} 
defined class Q 

scala> new { def as[M[_]](n:N[M]) = null}  
:7: error: can't existentially abstract over parameterized type M 
     new { def as[M[_]](n:N[M]) = null} 

0

: 당신이 언급 한 바와 같이 은 클래스에서 함수를 인코딩하면 블록 표현의 제한을 제거하는 블록이 캡처를 생성 할 때마다 생성 된 새로운 유형의 변수가있을 수 일부 유형 생성자는 실존 유형으로 인스턴스화되지만 오류 진단을 이해하기 어렵게 만듭니다.

클래스가 있으면 을() 메소드를 리플렉션으로 호출하는 대신 호출을 빠른 INVOKEVIRTUAL로 변경합니다.

관련 문제