복붙노트

[SCALA] 사용 사례 및 유형의 변수 유형의 패턴 예

SCALA

사용 사례 및 유형의 변수 유형의 패턴 예

나는 형 패턴 일치를 수행 할 때 스칼라 지원하는 형태 변수를 바인딩하는 사양을 읽는 발견 :

Map(1 -> "one", 2 -> "two") match {
  case l: Map[k, v] =>
    // binds k to Int and v to String
    // k and v are types as shown here:
    val i: Iterator[Tuple2[k, v]] = l.iterator
    println(i.mkString(", "))
}

이와 내가 할 수있는 멋진 일 또는 실제적인 일이 있습니까? 또는 형태 변수를 바인딩 유형의 문서 목적에만 유용합니다?

스칼라는 때때로 함수를 정의와 같은 유형의 주석을 필요로 나에게 발생, 그래서 나는 시도했다 :

def prepender(obj: Any) = obj match {
  case xs: List[a] => (x: a) => x :: xs
  case opt: Some[a] => (x: a) => x :: Nil
}

그러나 반환 함수의 유형은 이상한 :

prepender: (obj: Any)a with a => List[Any] forSome { type a; type a }

scala> val p = prepender(List(1,2))
p: a with a => List[Any] forSome { type a; type a } = <function1>

scala> p(1)
<console>:10: error: type mismatch;
 found   : Int(1)
 required: a(in value res7) with (some other)a(in value res7) where 
   type (some other)a(in value res7), type a(in value res7)

해결법

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

    1.난 왜의 처음 신속한 답변을 제공하기 위해 노력거야 것을, 나는이 너무 오래하지 희망,하지만 난 심각하게 의심 "당신이 (추상) 어떤 이름을 때, 주요 사용 사례 나중에 언급한다." 글쎄요, 지금은 도움이 되었습니까 아니었다?

    난 왜의 처음 신속한 답변을 제공하기 위해 노력거야 것을, 나는이 너무 오래하지 희망,하지만 난 심각하게 의심 "당신이 (추상) 어떤 이름을 때, 주요 사용 사례 나중에 언급한다." 글쎄요, 지금은 도움이 되었습니까 아니었다?

    이 간단한 스칼라 기능을 고려 :

    val sum = (a: Int, b: Int) => a + b
    

    컴파일러는이는 A이고 B는 B 것을 알 필요가 없습니다. 모든 그것은뿐만 아니라 B ​​형은 int 것을 알 필요가 a는 B 전에 온다 (이 것 중요하지,이 경우 또한이 교환 법칙이 성립하지만, 컴파일러 염려 어쨌든 때문에!). 스칼라 이벤트는이 "가설"의 증거로 작용 컴파일러 친화적 자리 구문을, (또한 사랑 나에게 잘못 I를하지 않습니다).

    val sum: (Int, Int) => Int = _ + _ // where the 1st _ differs from the 2nd _
    

    이제 이것 좀보세요 :

    case x: SomeTypeParameterizedWith[AnotherType] // AnotherType is erased anyway
    case x: SomeParameterizedType[_] // Existential type
    case x: SomeParameterizedType[kind] // Existential type which you can reference
    

    당신이 형식 인수에 대해 걱정하지 않는 경우 자리 표시 자 구문을 사용합니다. 당신이 (어떤 이유) 할 때 컴파일러는 식별자로 취급 할 알 수 있도록 당신이 낮은 경우와 형식 인수 이름을 지정해야 관심.

    귀하의 질문에 백업합니다.

    실존 유형에 대한 주요 용도는 자바의 와일드 카드 유형을 주위에 노력하고 있습니다. 이 스칼라 프로그래밍에서 가져옵니다 - 실존 적 유형을 약간 진정으로 당신에 의해 수정되었습니다.

    // This is a Java class with wildcards
    public class Wild {
      public java.util.Collection<?> contents() {
        java.util.Collection<String> stuff = new Vector<String>();
        stuff.add("a");
        stuff.add("b");
        stuff.add("see");
        return stuff;
      }
    }
    
    // This is the problem
    import scala.collection.mutable.Set
    val iter = (new Wild).contents.iterator
    val set = Set.empty[???] // what type goes here?
    while (iter.hasMore)
      set += iter.next()
    
    // This is the solution
    def javaSet2ScalaSet[T](jset: java.util.Collection[T]): Set[T] = {
      val sset = Set.empty[T] // now T can be named!
      val iter = jset.iterator
      while (iter.hasNext)
        sset += iter.next()
      sset
    }
    

    좋아, 그래서 무슨 일이 방금 일어 났는가? 단순 제네릭, 마법이?! 당신이 하루 기준으로 하루에 제네릭을 취급하는 경우 범위에 형식 인수를 도입 울트라 슈퍼 개념은 클래스와 메소드에 작동이 당신에게 정상 보이지만, 당신은 잊고있다. 당신은 (REPL 같은) 갑자기 중간에 어떤 임의의 범위에서, 클래스 나 메소드 이외의 어떤 경우에? 또는 당신은 어떤 클래스 나 메소드에 있지만 유형의 인수는 자신의 범위에 도입되지 않은 경우? 귀하의 질문이 답이 플레이하는 곳이다.

    val set = new Wild().contents match {
      case jset: java.util.Collection[kind] => {
        val sset = Set.empty[kind]
        val iter = jset.iterator
        while (iter.hasNext)
          sset += iter.next()
        sset
      }
    }
    

    컴파일러는이 같은 일을 언급하고 있는지 확인 할 수 있도록 식별자 종류가 필요합니다.

    참고, 세트의 유형 설정 [_] 때문에 그냥 세트로 문자열을 추가 할 수 없습니다.

  2. from https://stackoverflow.com/questions/7313948/use-case-and-examples-for-type-pattern-with-type-variable by cc-by-sa and MIT license