복붙노트

[SCALA] 왜 보조 기술은 타입 수준의 계산에 필요합니까?

SCALA

왜 보조 기술은 타입 수준의 계산에 필요합니까?

나는 볼품에 꽤 새로 온 이후 나는 확신 내가 여기서 뭔가를 누락 그리고 난 배우는 중이에요,하지만 때 보조 기술은 실제로 필요합니까? 나는 또 다른 "동반자"유형 정의의 서명으로 그것을 높여 유형 문을 노출하는 데 사용되는 것을 알 수있다.

trait F[A] { type R; def value: R }
object F { type Aux[A,RR] = F[A] { type R = RR } }

그러나 이것은 단지 F의 유형 서명에 R을 넣어 거의 동일하지 않습니다?

trait F[A,R] { def value: R }
implicit def fint = new F[Int,Long] { val value = 1L }
implicit def ffloat = new F[Float,Double] { val value = 2.0D }
def f[T,R](t:T)(implicit f: F[T,R]): R = f.value
f(100)    // res4: Long = 1L
f(100.0f) // res5: Double = 2.0

나는 하나의 인수 목록에서 사용할 수있는 경우 해당 경로에 의존하는 형태가 이익을 가져올 것이라고 볼 수 있지만, 우리는 우리가 할 수 없다는 것을 알아

def g[T](t:T)(implicit f: F[T], r: Blah[f.R]) ...

따라서, 우리는 여전히 g의 서명에 추가 입력 매개 변수를 넣어 강제로. 억스 기술을 사용하여, 우리는 또한 동반자 객체를 작성하는 추가 시간을 할애해야합니다. 전혀 경로 의존적 유형을 사용에 아무런 혜택이 없다는 사용의 관점에서, 그것은 나 같은 순진한 사용자에게 보일 것이다.

이 내가 한 종류 이상의 수준의 결과가 반환됩니다 지정된 유형 수준의 계산을 위해, 즉, 생각할 수있는 단 하나의 사건은, 당신은 그 중 하나를 사용할 수 있습니다.

나는 모두가 내 간단한 예에서 무언가를 바라 보는 나에게 귀결 것 같아요.

해결법

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

    1.여기에 두 개의 질문이 있습니다 :

    여기에 두 개의 질문이 있습니다 :

    대답은 더 간단하기 때문에 나는 두 번째 질문으로 시작합니다 : 억스 유형 별칭이 완전히 구문 편리합니다. 혹시을 사용할 필요가 없습니다. 예를 들어, 우리는 같은 길이를 가진 두 개의 hlists 호출 컴파일하는 방법을 작성한다고 가정 :

    import shapeless._, ops.hlist.Length
    
    def sameLength[A <: HList, B <: HList, N <: Nat](a: A, b: B)(implicit
      al: Length.Aux[A, N],
      bl: Length.Aux[B, N]
    ) = ()
    

    길이 타입 클래스합니다 (HList 타입에 대한) 하나 개의 입력 파라미터 (냇 대한) 하나의 입력 부재를 갖는다. Length.Aux 구문은 비교적 쉽게 암시 적 매개 변수 목록에서 냇 형 멤버를 참조 할 수 있습니다,하지만 그것은 단지 편리 - 더의 다음은 정확히 동일합니다 :

    def sameLength[A <: HList, B <: HList, N <: Nat](a: A, b: B)(implicit
      al: Length[A] { type Out = N },
      bl: Length[B] { type Out = N }
    ) = ()
    

    옥스 버전은 이러한 방법으로 유형의 개선을 작성하는 동안 몇 가지 장점이 있습니다 덜 시끄러운이고, 그것은 형식 멤버의 이름을 기억하기 위해 우리를 필요로하지 않습니다. 보조 별칭 읽기 및 쓰기에 좀 더 쉽게 우리의 코드를 만들어가 있지만 - 이들은 순수하게 인체 공학적 문제,하지만 그들은 우리가 또는 의미있는 방식으로 코드를 할 수있는 일과 할 수없는 일 변경되지 않습니다.

    첫 번째 질문에 대한 대답은 조금 더 복잡하다. 내 sameLength을 포함하여 대부분의 경우에서, 아웃 타입 멤버 대신 형식 매개 변수가되기 위해서는 어떤 이점이 없습니다. 스칼라 여러 암시 적 매개 변수 섹션을 허용하지 않기 때문에, 우리는 우리가 두 개의 길이 인스턴스가 동일한 출력 유형이 있는지 확인하려는 경우 N은 우리의 방법에 대한 형식 매개 변수해야합니다. 그 시점에서, 길이의 아웃도 (sameLength의 저자로 우리의 관점에서 적어도) 유형 매개 변수 일 수 있습니다.

    다른 경우에는, 그러나, 우리는 볼품 가끔 (내가 여기서 잠시 구체적으로는 약 얘기하자) 수 있다는 장점이 있습니다 유형의 멤버가 아닌 유형의 매개 변수를 사용합니다. 예를 들어, 우리가 HList로 지정된 경우 클래스 형식을 변환하는 함수를 반환하는 메소드를 작성한다고 가정 :

    def converter[A](implicit gen: Generic[A]): A => gen.Repr = a => gen.to(a)
    

    이제 우리는 다음과 같이 사용할 수 있습니다 :

    case class Foo(i: Int, s: String)
    
    val fooToHList = converter[Foo]
    

    그리고 우리는 좋은의 푸 => Int 인 :: 문자열 :: HNil를 얻을 수 있습니다. 일반의에 repr 대신 형 부재의 형식 매개 변수가 있다면, 우리는 대신 같은 것을 작성해야 할 것입니다 :

    // Doesn't compile
    def converter[A, R](implicit gen: Generic[A, R]): A => R = a => gen.to(a)
    

    스칼라 때마다 우리는이 (가상) 메소드를 호출 할 수 있도록 우리가를 지정하려면 이후 우리는 모두 유형 매개 변수를 지정해야 할 것, 형식 매개 변수의 일부 응용 프로그램을 지원하지 않습니다

    val fooToHList = converter[Foo, Int :: String :: HNil]
    

    전체 지점이 표현 밖으로 일반 기계 그림을 수 있도록했다 때문에, 그것은 기본적으로 쓸모 있습니다.

    일반적으로, 유형이 고유 한 유형 클래스의 다른 매개 변수에 의해 결정 될 때마다, 볼품는 타입 멤버 대신의 유형 매개 변수를 만들 것입니다. 일반은 (표현 유형) (경우에 클래스 유형에 대한) 하나 개의 입력 매개 변수 및 하나의 입력 부재를 갖도록 모든 경우 클래스는 단일의 일반적인 표현이있다; 모든 HList 번의 길이를 가지며, 그래서 길이는 1 개 타입 파라미터 및 하나 형 부재 등을 갖고

    유일하게 정해진 종류의 타입 멤버 대신 유형 매개 변수 수단을 만드는 것을 우리는 경로 의존적 유형과 같은 (위의 첫 번째 컨버터로)를 사용하려는 경우, 우리는 할 수 있지만,이 유형 매개 변수 인 것처럼 우리는 그들을 사용하려는 경우 우리는 항상 두 종류의 정제 (또는 보조 버전 좋네요 구문을) 밖으로 쓸 수 있습니다. 무형이 유형은 처음부터 매개 변수를 입력 한 경우, 그 반대 방향으로 갈 수 없을 것이다.

    사이드 참고로, '타입 클래스의 유형 "매개 변수"(그들은 문자 그대로 스칼라 의미에서 매개 변수를하지 않을 수 있기 때문에 나는 인용 부호를 사용하고 있습니다) 사이의 관계는 하스켈 같은 언어에서 "함수 적 종속성"라고,하지만 당신은 shouldn 당신처럼 t 느낌은 볼품에서 일어나는 것을 얻을 하스켈 함수 종속에 대해 아무것도 이해할 필요가있다.

  2. from https://stackoverflow.com/questions/34544660/why-is-the-aux-technique-required-for-type-level-computations by cc-by-sa and MIT license