나중에 Pimp My Library 패턴 에 따라 사용하려는 다음 클래스를 작성했습니다 .
class ListX[A] (list: List[A]) {
def zipMap[A, B, C] (that: List[B], op: (A, B) => C): List[C] =
list.zip(that).map({
case (a: A, b: B) => op(a, b)
})
}
이것은 경고와 함께 컴파일됩니다.
[warn] /src/main/scala/ListX.scala:8: abstract type pattern A is unchecked since it is eliminated by erasure
[warn] case (a: A, b: B) => op(a, b)
[warn] ^
[warn] /src/main/scala/ListX.scala:8: abstract type pattern B is unchecked since it is eliminated by erasure
[warn] case (a: A, b: B) => op(a, b)
[warn] ^
[warn] two warnings found
REPL에서 테스트하면 다음 오류가 발생합니다.
scala> val a = new ListX(List(1, 1, 1))
scala> val b = List(1, 1, 1)
scala> val result = a.zipMap(b, _ + _)
error: missing parameter type for expanded function ((x$1: <error>, x$2) => x$1.$plus(x$2))
scala> val expected = List(2, 2, 2)
나는 Scala를 처음 접했기 때문에 경고와 오류를 완전히 이해하지 못했습니다. "타입 삭제"라는 것이 있다는 것을 알고 있지만 작동 방식은 알 수 없으며 이것이 아마도 누락 된 유형으로 이어진다는 것을 알 수 있습니다.
그렇다면 무엇이 잘못되었으며 어떻게 수정할 수 있습니까?
최신 정보:
받아 들여진 답변과 의견 덕분에 문제를 수정하고 다음과 같이 수업을 다시 작성했습니다.
implicit class ListX[A] (list: List[A]) {
def zipMap[B, C] (that: List[B])(op: (A, B) => C): List[C]
= list.zip(that).map({ op.tupled })
}
코드에 많은 문제가 있습니다. 유형 삭제 뿐만이 아닙니다.
스칼라가 람다 유형을 파생 시키려면 별도의 인수 그룹에 (that: List[B])(op: (A, B) => C)
넣은 다음 zipMap(List(1, 1, 1))(_ + _)
. 여기에서 이에 대한 많은 답변을 찾을 수 있습니다. 요컨대 스칼라는 B
정의한 그룹의 유형 에 대해 알지 못하기 때문에 유형 을 지정한 첫 번째 그룹은 유형을 추론 할 수 없습니다.
그런 다음 유형 매개 변수를 A
두 번 정의 했습니다. 하나는 당신의 수업에, 다른 하나는 당신의 방법에 있습니다. 한 번만 필요합니다. Scala는이 두 A
가지 유형 매개 변수를 서로 다른 두 가지 유형 매개 변수로 이해 하므로 후자 A
는에 관련되지 않았기 때문에 실제 유형이 없으며 list: List[A]
scala에 대한 유형을 파생 할 수 없습니다 _ + _
.
그리고 ClassTag
유형 삭제와 싸우려면 유형 매개 변수에 대한 컨텍스트 바인딩 이 필요합니다 . 다음과 같이 작성한다 [A : ClassTag]
짧은이 스칼라 당신의 모두에 대해 형식 정보를 첨부 할 수에서 A
와 B
스칼라 경기에서 그것을 사용하기 위해.
따라서 결과 코드는 다음과 같습니다.
(답변 끝에있는 코드를 더 나은 버전으로 참조하십시오.이 버전은 단순화 될 수 있습니다)
class ListX[A : ClassTag](list: List[A]) {
def zipMap[B: ClassTag, C](that: List[B])(op: (A, B) => C): List[C] =
list.zip(that).map({
case (a: A, b: B) => op(a, b)
})
}
println(new ListX[Int](List(2, 2, 2)).zipMap(List(1, 1, 1))(_ + _))
최신 정보
@ Łukasz 댓글에 대해 조금 생각한 후 실수를 저질렀다는 것을 깨달았습니다 ClassTag
. 여기 에는 정말 필요하지 않습니다 . 경고를 생성 한 이유는 명시 적으로 case
유형을 가져야한다고 지정했기 때문 (A, B)
입니다. 대신 컴파일러에게 이것을 스스로 알아낼 기회를 줄 수 있고, 여기서 무슨 일이 일어나고 있는지 올바르게 이해한다면 컴파일러 ClassTag
는 아무것도하지 않기 때문에 여기서 s 가 필요하지 않다는 것을 알아낼 수 있습니다 . 이것 좀 봐:
class ListX[A](list: List[A]) {
def zipMap[B, C](that: List[B])(op: (A, B) => C): List[C] =
list.zip(that).map({
case (a, b) => op(a, b)
})
}
println(new ListX[Int](List(2, 2, 2)).zipMap(List(1, 1, 1))(_ + _))
이것은 경고를 생성하지 않습니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다