복붙노트

[SCALA] 스칼라 형 람다는 무엇인가 자신의 장점은 무엇입니까?

SCALA

스칼라 형 람다는 무엇인가 자신의 장점은 무엇입니까?

언젠가 나는의 반 신비 표기로 넘어

def f[T](..) = new T[({type l[A]=SomeType[A,..]})#l] {..} 

그것을 줄 스칼라 블로그 게시물에서는 아예 무시해 "우리는 타입 람다 트릭을 사용".

나는이에 대한 몇 가지 intutition을 가지고 있지만 (우리가 그것으로 정의를 오염하지 않고 익명의 형식 매개 변수 A를 얻을?), 나는 형 람다 트릭이 무엇인지 설명하는 명확한 원인을 발견하고, 그 혜택은 무엇인가. 그냥 문법 설탕인가, 아니면 새로운 차원을 열 수 있는가?

해결법

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

    1.타입 람다는 높은 kinded 종류의 작업 시간이 꽤 중요합니다.

    타입 람다는 높은 kinded 종류의 작업 시간이 꽤 중요합니다.

    어느 [A, B]의 오른쪽 투사 모나드를 정의하는 간단한 예를 고려한다. 모나드 typeclass은 다음과 같습니다 :

    trait Monad[M[_]] {
      def point[A](a: A): M[A]
      def bind[A, B](m: M[A])(f: A => M[B]): M[B]
    }
    

    이제, 하나는 두 개의 인수의 타입 생성자가 있지만 모나드를 구현하기 위해, 당신은 그것을 하나 개의 인수의 타입 생성자를 제공 할 필요가있다. 이에 대한 해결책은 형 람다를 사용하는 것입니다 :

    class EitherMonad[A] extends Monad[({type λ[α] = Either[A, α]})#λ] {
      def point[B](b: B): Either[A, B]
      def bind[B, C](m: Either[A, B])(f: B => Either[A, C]): Either[A, C]
    }
    

    당신은 당신이 EitherMonad의 인스턴스를 생성 할 때, 당신은 유형 중 하나를 지정해야합니다 있도록, 하나의 유형을 카레 한 -이 타입 시스템에 무두질의 예입니다 물론 다른 하나는 당신이 포인트 또는 바인드를 호출 할 때 제공됩니다.

    타입 람다 트릭 타입 위치에 빈 블록이 익명 형 구조를 생성한다는 사실을 이용한다. 우리는 다음 유형의 멤버를 얻기 위해 # 구문을 사용합니다.

    경우에 따라서는 인라인을 작성하는 고통이다 그보다 정교한 타입의 람다를해야 할 수도 있습니다. 다음은 오늘부터 내 코드의 예입니다 :

    // types X and E are defined in an enclosing scope
    private[iteratee] class FG[F[_[_], _], G[_]] {
      type FGA[A] = F[G, A]
      type IterateeM[A] = IterateeT[X, E, FGA, A] 
    }
    

    내가 몇 번째 모나드를 전문으로하는 두 번째 모나드의 일부 변압기 버전으로 전문 IterateeT 모나드의 유형을 참조 FG [F, G] #IterateeM 같은 이름을 사용할 수 있도록이 클래스는 단독으로 존재한다. 당신은 스택 시작하면 구조의 이러한 종류는 매우 필요하게된다. 나는 과정의 FG를 인스턴스화하지; 그것은 나를 내가 타입 시스템에서 원하는 것을 표현할 수 있도록 해킹으로 단지가있다.

  2. ==============================

    2.장점은 정확히 익명 함수에 의해 부여 된 것과 동일합니다.

    장점은 정확히 익명 함수에 의해 부여 된 것과 동일합니다.

    def inc(a: Int) = a + 1; List(1, 2, 3).map(inc)
    
    List(1, 2, 3).map(a => a + 1)
    

    사용 예는, Scalaz 7에서 우리는 Tuple2에서 두 번째 요소를 통해 기능을 매핑 할 수 있습니다 펑터를 사용하고 싶습니다.

    type IntTuple[+A]=(Int, A)
    Functor[IntTuple].map((1, 2))(a => a + 1)) // (1, 3)
    
    Functor[({type l[a] = (Int, a)})#l].map((1, 2))(a => a + 1)) // (1, 3)
    

    Scalaz는 펑터 형식 인수를 유추 할 수있는 몇 가지 암시 적 변환을 제공합니다, 그래서 우리는 종종 모두이를 작성하지 마십시오. 이전 라인은 다음과 같이 쓸 수있다 :

    (1, 2).map(a => a + 1) // (1, 3)
    

    당신이 인 IntelliJ를 사용하는 경우,이 설정을 사용할 수 있습니다, 코드 스타일, 스칼라, 접기, 유형 람다. 이 구문은 다음의 crufty 부분을 숨 깁니다, 그리고 더 맛 제시한다 :

    Functor[[a]=(Int, a)].map((1, 2))(a => a + 1)) // (1, 3)
    

    스칼라의 미래 버전은 바로 이러한 구문을 지원할 수 있습니다.

  3. ==============================

    3.문맥에 물건을 넣으려면 :이 답변은 원래 다른 스레드에 게시했습니다. 두 개의 스레드가 통합되었습니다 때문에 여기를보고있다. 다음과 같이 말했다 스레드 질문 문을했다 :

    문맥에 물건을 넣으려면 :이 답변은 원래 다른 스레드에 게시했습니다. 두 개의 스레드가 통합되었습니다 때문에 여기를보고있다. 다음과 같이 말했다 스레드 질문 문을했다 :

    대답:

    trait Pure[P[_]] {
      def pure[A](a: => A): P[A]
    }
    

    P는이 타입 생성자는 하나의 형식을 취하고 다른 형식을 반환하는 것을 의미한다 후 하나는 상자에서 밑줄. 목록 옵션 : 이런 종류의 타입 생성자의 예.

    목록에게 INT, 구체적인 유형을주고, 당신 목록 [지능]를, 또 다른 구체적인 유형을 제공합니다. 목록에게 문자열을주고 그것은 당신에게 목록 [문자열]을 제공합니다. 기타.

    > * - 그래서, 목록이 옵션은 1. 공식적으로 우리가 말할 인수에 대응의 타입 수준의 기능으로 간주 될 수있다, 그들은 일종의 * 있습니다. 별표 타입을 나타낸다.

    이제 Tuple2 [_, _가] 종류의 타입 생성자는 (*, *) -> * 즉 새로운 유형을 얻기 위해 그것을 두 가지 유형을 제공해야합니다.

    자신의 서명이 일치하지 않기 때문에, 당신은 우리에게 어떤 *와 타입 생성자 줄 것이다 당신이 부분적으로 인수 중 하나 Tuple2을 적용하기 만하면 무엇 P.에 대한 Tuple2, 대체 할 수 -> *을, 우리는 P를 위해 그것을 대체 값 수 .

    불행하게도 스칼라 타입 생성자의 일부 응용 프로그램에 대한 특별한 구문이 없으며, 그래서 우리는 괴물이라는 형 람다에 의존해야합니다. (당신이 당신의 예에서 무엇을 가지고.) 그들은이라고 그들이 가치 수준에서 존재하는 람다 표현식와 유사하기 때문이다.

    다음 예는 도움이 될 수 있습니다 :

    // VALUE LEVEL
    
    // foo has signature: (String, String) => String
    scala> def foo(x: String, y: String): String = x + " " + y
    foo: (x: String, y: String)String
    
    // world wants a parameter of type String => String    
    scala> def world(f: String => String): String = f("world")
    world: (f: String => String)String
    
    // So we use a lambda expression that partially applies foo on one parameter
    // to yield a value of type String => String
    scala> world(x => foo("hello", x))
    res0: String = hello world
    
    
    // TYPE LEVEL
    
    // Foo has a kind (*, *) -> *
    scala> type Foo[A, B] = Map[A, B]
    defined type alias Foo
    
    // World wants a parameter of kind * -> *
    scala> type World[M[_]] = M[Int]
    defined type alias World
    
    // So we use a lambda lambda that partially applies Foo on one parameter
    // to yield a type of kind * -> *
    scala> type X[A] = World[({ type M[A] = Foo[String, A] })#M]
    defined type alias X
    
    // Test the equality of two types. (If this compiles, it means they're equal.)
    scala> implicitly[X[Int] =:= Foo[String, Int]]
    res2: =:=[X[Int],Foo[String,Int]] = <function1>
    

    편집하다:

    값 수준 및 유형 레벨 평행선 더.

    // VALUE LEVEL
    
    // Instead of a lambda, you can define a named function beforehand...
    scala> val g: String => String = x => foo("hello", x)
    g: String => String = <function1>
    
    // ...and use it.
    scala> world(g)
    res3: String = hello world
    
    // TYPE LEVEL
    
    // Same applies at type level too.
    scala> type G[A] = Foo[String, A]
    defined type alias G
    
    scala> implicitly[X =:= Foo[String, Int]]
    res5: =:=[X,Foo[String,Int]] = <function1>
    
    scala> type T = World[G]
    defined type alias T
    
    scala> implicitly[T =:= Foo[String, Int]]
    res6: =:=[T,Foo[String,Int]] = <function1>
    

    경우에 당신은 형식 매개 변수의 R은 Tuple2Pure를 작동하기 때문에 단순히 유형을 정의 할 수 없습니다 로컬, 제시 PartialTuple2 [A] = Tuple2 [R, A], 단순히 당신이 동의어를 넣을 수있는 곳이 없기 때문입니다.

    이러한 경우에 대처하기 위해, 나는 형의 멤버를 사용합니다 다음과 같은 트릭을 사용합니다. (희망 예는 자명하다.)

    scala> type Partial2[F[_, _], A] = {
         |   type Get[B] = F[A, B]
         | }
    defined type alias Partial2
    
    scala> implicit def Tuple2Pure[R]: Pure[Partial2[Tuple2, R]#Get] = sys.error("")
    Tuple2Pure: [R]=> Pure[[B](R, B)]
    
  4. ==============================

    4.입력 세계 [M [_]] = M [Int 인은] 우리가 X에 넣어 무엇이든 원인 [A] 암시 [X [A] = = 푸 [문자열, 지능이] 항상 같아요 사실이다.

    입력 세계 [M [_]] = M [Int 인은] 우리가 X에 넣어 무엇이든 원인 [A] 암시 [X [A] = = 푸 [문자열, 지능이] 항상 같아요 사실이다.

  5. from https://stackoverflow.com/questions/8736164/what-are-type-lambdas-in-scala-and-what-are-their-benefits by cc-by-sa and MIT license