scala에는 특정 타입을 만족하는 증거(witness)를 의미한다.
implicit evidence는 허용할 타입을 제한함을 의미한다.
간단하게 아래 내용을 테스트해본다.
val list1 = List("a" -> "b", "c" -> "d", "e" -> "f")
println(list1.toMap)
이 결과는 다음과 같다.
Map(a -> b, c -> d, e -> f)
toMap은 암시를 받는데, <:<를 사용한다. A는 (T, U) 타입의 서브 타입, 즉 튜플이어야 함을 의미한다.
def toMap[T, U](implicit ev: A <:< (T, U)): immutable.Map[T, U] = {
val b = immutable.Map.newBuilder[T, U]
for (x <- self)
b += x
b.result()
}
만약, 아래 코드를 실행했다면, 에러가 발생했을 것이다.
val list1 = List(1,2,3,4,5)
list1.toMap // Error:(8, 6) Cannot prove that Int <:< (T, U).
implicit을 쓰지 않아도 암시로 쓰일 수 있다.
scala> def impTest[X : Seq](x : X) = x
impTest: [X](x: X)(implicit evidence$1: Seq[X])X
Predef.scala의 일부 내용에 다음과 같이 쓰여져 있다.
/**
* An instance of `A <:< B` witnesses that `A` is a subtype of `B`.
* Requiring an implicit argument of the type `A <:< B` encodes
* the generalized constraint `A <: B`.
*
* @note we need a new type constructor `<:<` and evidence `conforms`,
* as reusing `Function1` and `identity` leads to ambiguities in
* case of type errors (`any2stringadd` is inferred)
*
* To constrain any abstract type T that's in scope in a method's
* argument list (not just the method's own type parameters) simply
* add an implicit argument of type `T <:< U`, where `U` is the required
* upper bound; or for lower-bounds, use: `L <:< T`, where `L` is the
* required lower bound.
*
* In part contributed by Jason Zaugg.
*/
@implicitNotFound(msg = "Cannot prove that ${From} <:< ${To}.")
sealed abstract class <:<[-From, +To] extends (From => To) with Serializable
private[this] final val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x }
// The dollar prefix is to dodge accidental shadowing of this method
// by a user-defined method of the same name (SI-7788).
// The collections rely on this method.
implicit def $conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]
@deprecated("Use `implicitly[T <:< U]` or `identity` instead.", "2.11.0")
def conforms[A]: A <:< A = $conforms[A]
/** An instance of `A =:= B` witnesses that the types `A` and `B` are equal.
*
* @see `<:<` for expressing subtyping constraints
*/
@implicitNotFound(msg = "Cannot prove that ${From} =:= ${To}.")
sealed abstract class =:=[From, To] extends (From => To) with Serializable
private[this] final val singleton_=:= = new =:=[Any,Any] { def apply(x: Any): Any = x }
object =:= {
implicit def tpEquals[A]: A =:= A = singleton_=:=.asInstanceOf[A =:= A]
}
'scala' 카테고리의 다른 글
[scala] sys.env 환경변수 확인 예시 (0) | 2016.11.07 |
---|---|
[zeppelin] 외부 lib 추가하기 (0) | 2016.11.05 |
[scala] 암시 implicitly (0) | 2016.11.03 |
[scala] 문자열 패턴 매치 (pattern match) 예시 (0) | 2016.11.02 |
[scala] 참조 투명성(referential transparency)과 부작용(side effect) (0) | 2016.10.31 |