2

, 형질 내부 다음 방법 읽어가 [A] :재생 소스 파일 "Reads.scala"사용은 Play 워크 소스 파일

def andThen[B](rb: Reads[B])(implicit witness: A <:< JsValue): Reads[B] = 
    rb.compose(this.map(witness)) 

이 같은지도 방법 (일반화 된 형태 인 제약) < JsValue :

def map[B](f: A => B): Reads[B] = 
    Reads[B] { json => self.reads(json).map(f) } 

증인 < A 형이다. 그러면지도 메소드의 매개 변수가 함수 f를 취할 때 인수로 map 메소드에 전달되는 방법은 무엇입니까? A ​​=> B ??

누군가 설명 할 수 있습니까? 감사!

답변

4

이 유형 감시는 또한 기능이기 때문입니다. Predef로 선언 :

sealed abstract class <:<[-From, +To] extends (From => To) with Serializable 

그래서 A <:< JsValue도 기능 (A) => JsValue이다. 함수가 무엇을하는지 궁금 할 수 있습니다. 아무 것도하지 않고 A을 사용하고 직접 반환합니다 (JsValue).

sealed trait Root { def bip() { println("bip") } } 

def makeBip[A <: Root](a: A) { 
    a.bip() // works because a is known to the type system to be a Root 
} 

def makeBip2[A](a: A)(implicit ev: A <:< Root) { 
    a.bip() // works, because implicit resolution turns it into `ev(a).bip()` 
} 

비록 당신이 a 증거에 Root 감사 것을 알고 때문에 makeBip2가 암시하지 않고 컴파일되지 것이다 마지막 방법, 유형이이 예제를 고려 유용한 이유

은 참조하십시오 시스템은 그렇지 않습니다. 당신은 그것을 캐스팅 할 수 있습니다, 그것은 일하게 될 것입니다 :

def makeBip3[A](a: A)(implicit ev: A <:< Root) { 
    a.asInstanceOf[Root].bip() // ugly 
} 

그러나 이것은 옳지 않습니다. 단지 당신이 aRoot으로 변환하는 방법을 가지고 있다면 ... 그러나 기다리십시오, 당신은 : 증거 그 자체! 암시 적 매개 변수는 메소드 내 implicits으로 사용할 수 있기 때문에

def makeBip4[A](a: A)(implicit ev: A <:< Root) { 
    ev(a).bip() // works! 
} 

는 그리고, a.bip() 자동 ev(a).bip()으로 변환됩니다 당신은 함수가 포함 된 알 필요가 없습니다.

그러나, 타입 시스템 만 Reads[JsValue]으로하는 A JsValueA 아니지만 Seq[A]Seq[JsValue]로 또는 Reads[A]를 해결하기 위해 암시를 사용합니다.

그래서 당신이 경우에, this.map(witness) 단지 형 시스템이 Reads[A]이가 JsValue를 취하고 B을 반환 뭔가로 구성 될 수 있도록, 아무것도하지 않는 해당 기능을 적용하여 Reads[JsValue]을 것을 이해한다.

자세한 내용은 Generalized type constraits 질문을 참조하십시오.