2016-11-06 2 views
3

스칼라를 실험하고 형식 유추 문제로 약간 혼란스러워합니다. 컴파일러 오류에스칼라의 일반 카레 메서드에 대한 유추 형식

val hist = SequentialHistory(Seq.empty[Event]) 
//hist: SequentialHistory[Event] = SequentialHistory(List()) 

val histWithEvent = addEvent(SampleEvent("Does not compile"))(hist) 
//error 

결과 : 형식 유추가 제대로 컴파일 작동하지 않는 이유

case class SequentialHistory[+E](events: Seq[E]) 

trait Event 

case class SampleEvent(value: String) extends Event 

def addEvent[E, E2 >: E](event: E)(history:SequentialHistory[E2]): 
SequentialHistory[E2] = history.copy(events = event +: history.events) 
싶습니다

이해하기 :

성공적으로 컴파일 아래의 정의를 감안할 때

Error:(21, 62) type mismatch; 
       found : SequentialHistory[Event] 
       required: SequentialHistory[SampleEvent] 
       addEvent(SampleEvent("Does not compile"))(hist) 
          ^

그러나 내가 addEvent 방법 정의에 매개 변수 목록을 교환하는 경우 : 문제를 해결할 것

def addEvent2[E, E2 >: E](history: SequentialHistory[E2])(event: E): 
SequentialHistory[E2] = history.copy(events = event +: history.events) 

는, 종류가 올바르게 추론 아래 조각은 컴파일 :

val hist2 = SequentialHistory(Seq.empty[Event]) 
//hist2: SequentialHistory[Event] = SequentialHistory(List()) 

val histWithEvent2 = addEvent2(hist)(SampleEvent("Compiles")) 
//histWithEvent1: SequentialHistory[Event] = 
// SequentialHistory(List(SampleEvent1(Compiles))) 

스칼라 컴파일러가 추론은`t 왜 유형을 올바르게 addEvent의 첫 번째 버전에 있습니까?

답변

1

컴파일러 코드 또는 스칼라 사양의 따옴표에 대해서는 설명 할 수 없지만 여기에는 제 추론이 있습니다.

함수에 여러 매개 변수 목록이있는 경우 "curried"이므로 다른 함수 등을 반환하는 첫 번째 인수의 함수입니다. 따라서 한 인수에만 적용하려고하면 모든 형식이 유추됩니다.

scala> val partial = addEvent(SampleEvent(""))(_) 
partial: SequentialHistory[SampleEvent] => SequentialHistory[SampleEvent] = <function1> 

이제 더 넓은 유형의 두 번째 인수를 전달할 수 없습니다. 여기에서 일어나는 일은 eta expansion입니다.

scala> val partial = addEvent2(hist)(_) 
<console>:14: error: missing parameter type for expanded function ((x$1) => addEvent2(hist)(x$1)) 
     val partial = addEvent2(hist)(_) 
다음

E2hist 인수로 고정되어 있지만, 컴파일러는 E을 추론 할 수없는 :하지만 라운드 다른 방법이 작동하지 않습니다. 그러나 두 인수를 모두 제공하면 유형이 제한 사항을 준수하는 것으로 간주됩니다. 이 의미에서 두 번째 정의는 def addEvent2[E, E2 >: E](event: E, history: SequentialHistory[E2])처럼 정의하는 것과 같다고 생각합니다.

+1

기술적으로 여러 매개 변수 목록과 currying (스칼라 문서가 정의하는 방식이 아닌 고전적)은 두 가지 개념입니다. 잠재적 η 확장이 유형 유추에 영향을 미친다고 말하는 겁니까? 이상 할거야. –

+0

모든 매개 변수가 하나의 매개 변수 목록에있는 경우 - 형식 유추가 다르게 동작합니다 ("병렬"로 유추 함). 하나의 매개 변수 목록에서도 여러 매개 변수에 부분 적용이 가능하므로 이유가없는 것 같습니다. – dk14