복붙노트

[SCALA] 어떻게 문맥에 관련한 타입 클래스의 인스턴스 바인딩을받을 수 있나요?

SCALA

어떻게 문맥에 관련한 타입 클래스의 인스턴스 바인딩을받을 수 있나요?

참고 : 내가 직접 대답이 질문에 포즈를하고있어,하지만 다른 답변을 환영합니다.

다음과 같은 간단한 방법을 고려 :

def add[T](x: T, y: T)(implicit num: Numeric[T]) = num.plus(x,y)

나는 다음과 같이 바인딩 컨텍스트를 사용하여 다시 작성할 수 있습니다

def add[T: Numeric](x: T, y: T) = ??.plus(x,y) 

하지만 어떻게 숫자 [T]의 인스턴스 내가 플러스 메소드를 호출 할 수 있도록 입력받을 수 있나요?

해결법

  1. ==============================

    1.암시 적 방법을 사용하여

    암시 적 방법을 사용하여

    가장 일반적이고 일반적인 접근 방식은 PREDEF에 정의 된 암시 적 방법을 사용하는 것입니다 :

    def add[T: Numeric](x: T, y: T) = implicitly[Numeric[T]].plus(x,y)
    

    분명히, 이것은 다소 장황하고 타입 클래스의 이름을 반복해야합니다.

    증거 매개 변수를 참조하는 (하지 않습니다!)

    또 다른 대안은 자동으로 컴파일러에 의해 생성 된 암시 적 증거 매개 변수의 이름을 사용하는 것입니다 :

    def add[T: Numeric](x: T, y: T) = evidence$1.plus(x,y)
    

    이 기술은 심지어 합법적 것은 놀라운 일이고, 그것은 변경 될 수 있습니다 증거 매개 변수의 이름부터 연습에 의존해서는 안됩니다.

    고등 종류의 컨텍스트 (문맥 도입 방법)

    대신에, 하나는 암시 적 방법의 강화 된 버전을 사용할 수 있습니다. 암시 적 방법은 다음과 같이 정의되어 있습니다

    def implicitly[T](implicit e: T): T = e
    

    이 방법은 단순히 메소드 호출로 주변 범위에서 올바른 유형의 암시 적 개체를 삽입하는 컴파일러에 의존하고 돌려줍니다. 우리는 더 나은 약간의 작업을 수행 할 수 있습니다

    def context[C[_], T](implicit e: C[T]) = e
    

    이것은 우리의 add 메소드를 정의 할 수있게 해준다

    def add[T: Numeric](x: T, y: T) = context.plus(x,y)
    

    문맥에있어서 타입 파라미터 T는 숫자 및 범위로부터 추론! 불행하게도,이 상황에 맞는 방법이 작동하지 않습니다하는 경우가있다. 타입 파라미터는 여러 문맥 범위를 갖거나 다른 컨텍스트 경계 여러 파라미터들은 예를 들면, 존재하는 경우. 우리는 조금 더 복잡한 버전으로 후자의 문제를 해결할 수 있습니다 :

    class Context[T] { def apply[C[_]]()(implicit e: C[T]) = e }
    def context[T] = new Context[T]
    

    이 버전마다 매개 변수 유형을 지정하기 위해 우리를 필요로하지만, 여러 유형 매개 변수를 처리합니다.

    def add[T: Numeric](x: T, y: T) = context[T]().plus(x,y)
    
  2. ==============================

    2.스칼라 2.9 이후 적어도 다음을 수행 할 수 있습니다 :

    스칼라 2.9 이후 적어도 다음을 수행 할 수 있습니다 :

    import Numeric.Implicits._
    def add[T: Numeric](x: T, y: T) = x + y
    
    add(2.8, 0.1) // res1: Double = 2.9
    add(1, 2) // res2: Int = 3
    
  3. ==============================

    3.이 답변은 다른 접근 방식을 설명하는 더 읽을 수있는, 자기 문서화 클라이언트 코드의 결과.

    이 답변은 다른 접근 방식을 설명하는 더 읽을 수있는, 자기 문서화 클라이언트 코드의 결과.

    동기

    내가 설명하는 문맥 방법은 이전에 별도의 노력없이, 모든 종류의 클래스로 작동하는 매우 일반적인 솔루션입니다. 그러나, 그것은 두 가지 이유로 바람직하지 않을 수 :

    타입 클래스 고유의 방법

    원하는 타입 클래스 차종 클라이언트 코드에 더 많은 읽을 수 연결하는 방법을 사용. 이 매니페스트 타입 클래스의 표준 라이브러리에서 사용하는 방법입니다 :

    // definition in Predef
    def manifest[T](implicit m: Manifest[T]) = m
    
    // example usage
    def getErasure[T: Manifest](x: T) = manifest[T].erasure
    

    이 방법을 일반화

    타입 급 전용 방법을 사용하는 주요 단점은 부가적인 방법은 모든 종류의 클래스 정의되어야한다는 것이다. 우리는 다음과 같은 정의에이 과정을 쉽게 할 수 있습니다 :

    class Implicitly[TC[_]] { def apply[T]()(implicit e: TC[T]) = e }
    object Implicitly { def apply[TC[_]] = new Implicitly[TC] }
    

    그런 다음 새로운 유형의 클래스 별 암시 적 스타일의 방법은 모든 종류의 클래스, 정의 할 수 있습니다 :

    def numeric = Implicitly[Numeric]
    // or
    val numeric = Implicitly[Numeric]
    

    마지막으로 다음과 같이, 클라이언트 코드는 암시를 사용할 수 있습니다 :

    def add[T: Numeric](x: T, y: T) = numeric[T].plus(x, y)
    
  4. from https://stackoverflow.com/questions/4373070/how-do-i-get-an-instance-of-the-type-class-associated-with-a-context-bound by cc-by-sa and MIT license