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]
}




Posted by '김용환'
,