2009-02-26 10 views
10

스칼라에서 멤버 유형이 어떻게 작동하는지 그리고 유형을 어떻게 연관시켜야하는지 알고 싶습니다.유형 매개 변수 대 스칼라의 멤버 유형

한 가지 방법은 관련 유형을 유형 매개 변수로 만드는 것입니다. 이 접근법의 장점은 유형의 분산을 처방 할 수 있다는 것이고 하위 유형이 유형을 변경하지 않는다는 것을 확신 할 수 있습니다. 단점은 함수의 형식에서 형식 매개 변수를 추론 할 수 없다는 것입니다.

두 번째 방법은 관련된 유형을 두 번째 유형의 멤버로 만드는 것이고 하위 유형의 연결된 유형에 경계를 지정할 수 없으므로 함수 매개 변수에서 유형을 사용할 수 없다는 문제가 있습니다. 구체적인 예로들 수

: (X, X 번호 (T)가 된 xT와 어떤 관련되지 않을 수 있습니다 때 X) :

내가

trait DFA[S] { /* S is the type of the symbols in the alphabet */ 
    trait State { def next(x : S); } 
    /* final type Sigma = S */ 
} 
(유형 매개 변수없이 수) DFAS에 대한 특성을 가지고

나는 달리기를위한 함수를 만들고 싶다. 이 입력 순서를 통해 DFA, 나는

  • 기능이 입력 순서 유형으로 아무것도 <% Seq[alphabet-type-of-the-dfa]를 수행해야 할
  • 유형 매개 변수를 지정할 필요가 없습니다 함수 호출은 모두 추정해야
  • 내가 좋겠 구체적인 DFA 유형으로 호출 할 함수와 같습니다 (그러나 함수가 DFA의 유형 매개 변수를 갖지 않는 솔루션이있는 경우에는 문제가 없습니다.)
  • 알파벳 유형은 제약을받지 않아야합니다.

    def runDFA[S, D <: DFA[S], SQ <% Seq[S]](d : D)(seq : SQ) = .... 
    

    이 작품 : 지금까지 알려지지 않은 사용자 정의 클래스 숯불뿐만 아니라위한 DFA) 다른 알파벳 유형

  • DFAS 내가이 시도

하위 유형이없는이 있어야합니다 단, S가 유추되지 않는다는 점을 제외하고는 각 호출 사이트에 전체 유형 매개 변수 목록을 작성해야합니다.

def runDFA[D <: DFA[S] forSome { type S }, SQ <% Seq[D#Sigma]](... same as above 

이 나는 ​​또한, 유형 매개 변수를 삭제 추상적 인 유형 시그마를 생성하고 그 유형을 결합 시도

(D를 ??? (무엇입니까?)를 입력하는 잘못된 순환 참조)를 작동하지 않았다 구체적인 수업. runDFA는

def runDFA[D <: DFA, SQ <% Seq[D#Sigma]](... same as above 

과 같을 것이다 그러나 이것은 필연적으로 같은 문제로 실행 "형식이 일치 : dfa.Sigma을 예상, D#Sigma 얻었다"

어떤 아이디어? 포인터?

편집 : 답변으로

가이 일 때문에 변경할 수 누군가가 왜 불가능하다 더에 정교한 수있는 어떤 것,이 일을 더 간단한 방법이없는 표시?

runDFA ro가 무료 함수 (메소드가 아님)가되기를 원하는 이유는 automaton 최소화, 정규 언어 연산, NFA-DFA 변환, 언어 분해 등과 같은 다른 유사한 함수를 원하고 이 한 클래스 안에서는 객체 지향 디자인의 거의 모든 원칙에 위배됩니다.

+0

와우, 나는 당신이 이것을 의미한다고 생각했다 : http://www.huygens-fokker.org/scala/ – MusiGenesis

답변

3

첫째로, 당신은 파라미터 설정의 SQ에게 <퍼센트 서열을 [이 필요하지 않습니다 에스]. 메서드 매개 변수를 Seq [S]로 씁니다. SQ < % Seq [S]이면 그 인스턴스는 Seq [S] (암시 적으로 < % 의미)로 암시 적으로 변환되므로 Seq [S]로 전달되면 컴파일러에서 자동으로 변환을 삽입합니다.

또한 Jorge는 D에 대한 매개 변수를 입력하고 DFA 보류에 대한 메서드로 사용한다고 말했습니다. 스칼라에서 내부 클래스가 작동하는 방식 때문에 은 DFA에 runDFA를 넣는 것이 좋습니다. 경로에 의존하는 타이핑 작업이 이루어지기 전까지는 외부 클래스의 내부 클래스를 다루는 것은 약간의 고통이 될 수 있습니다.

그래서 지금 당신은

trait DFA[S]{ 
    ... 

    def runDFA(seq : Seq[S]) = ... 
} 

을 그리고 runDFA는의 형식 매개 변수를 추정 오히려 쉽게 갑자기 : 그것은 어떤이 없습니다.

3

스칼라의 유추 추론은 때로는 많이 필요합니다.

DFA 특성 내에이 방법을 사용할 수없는 이유가 있습니까? 당신이 D의 PARAM 나중에 필요가없는 경우

def run[SQ <% Seq[S]](seq: SQ) 

, 당신은 또한 그것없이 당신의 방법을 정의하는 시도 할 수 있습니다 :

def runDFA[S, SQ <% Seq[S]](d: DFA[S])(seq: SQ) = ... 
0

에 대한 몇 가지 유용한 정보를 방법이 다릅니다 다음에서

무형의 guide :

당신이 여기에 예를

trait Generic[A] { 
    type Repr 
    def to(value: A): Repr 
    def from(value: Repr): A 
} 

import shapeless.Generic 
def getRepr[A](value: A)(implicit gen: Generic[A]) = 
    gen.to(value) 

에 의해 반환되는 유형, 의존적 유형을 할 수 없습니다 유형 매개 변수없이 to은 입력 유형 A에 따라 다릅니다 (제공된 암시 적 값은 A에 따라 다르기 때문에) :

case class Vec(x: Int, y: Int) 
case class Rect(origin: Vec, size: Vec) 
getRepr(Vec(1, 2)) 
// res1: shapeless.::[Int,shapeless.::[Int,shapeless.HNil]] = 1 :: 2 :: 
    HNil 
getRepr(Rect(Vec(0, 0), Vec(5, 5))) 
// res2: shapeless.::[Vec,shapeless.::[Vec,shapeless.HNil]] = Vec(0,0) 
    :: Vec(5,5) :: HNil 

형 멤버하지 않고는 불가능하다 : 우리는했을 것이다

trait Generic2[A, Repr] 
def getRepr2[A, R](value: A)(implicit generic: Generic2[A, R]): R = 
    ??? 

이 배우게 vely getRepr 쓸모 제작하는 를 입력 매개 변수로 getRepr에에 repr의 원하는 값을 전달합니다. 이 부분으로부터 라고 생각하면 형식 매개 변수가 "입력"으로 유용하고 유형의 멤버가 "출력"으로 유용하다는 것입니다.

자세한 내용은 모양이없는 guide을 참조하십시오.