[SCALA] 형의 클래스 인스턴스를 보장하기 위해 "부정적인"상황에 맞는 경계를 사용하면 범위에서 결석
SCALA형의 클래스 인스턴스를 보장하기 위해 "부정적인"상황에 맞는 경계를 사용하면 범위에서 결석
TL; DR : 어떻게 아래 만들어 코드와 같은 일을 수행합니다
def notFunctor[M[_] : Not[Functor]](m: M[_]) = s"$m is not a functor"
'[펑 터는]되지 않음', 여기에 일부를 만들어지고. 나는 그것이 제공하는 'm'이 펑터하지 않을 때 성공하고, 그렇지 않으면 컴파일러를 실패합니다.
해결 : 질문의 나머지를 건너 뛰고 아래의 답변을 바로 가서.
내가 달성 노력하고있어 대략 "부정적인 증거", 말하기,이다.
의사 코드는 지금과 같이 보일 것입니다 :
// type class for obtaining serialization size in bytes.
trait SizeOf[A] { def sizeOf(a: A): Long }
// type class specialized for types whose size may vary between instances
trait VarSizeOf[A] extends SizeOf[A]
// type class specialized for types whose elements share the same size (e.g. Int)
trait FixedSizeOf[A] extends SizeOf[A] {
def fixedSize: Long
def sizeOf(a: A) = fixedSize
}
// SizeOf for container with fixed-sized elements and Length (using scalaz.Length)
implicit def fixedSizeOf[T[_] : Length, A : FixedSizeOf] = new VarSizeOf[T[A]] {
def sizeOf(as: T[A]) = ... // length(as) * sizeOf[A]
}
// SizeOf for container with scalaz.Foldable, and elements with VarSizeOf
implicit def foldSizeOf[T[_] : Foldable, A : SizeOf] = new VarSizeOf[T[A]] {
def sizeOf(as: T[A]) = ... // foldMap(a => sizeOf(a))
}
그것은 우리에게 컬렉션을 통해 탐색을 절약 할 수 있기 때문에 fixedSizeOf ()는, 적절한 경우 바람직 있음을 유의하십시오.
이 방법은, 단지 길이가 정의 (그러나 접이식되지 않음)되는 컨테이너 유형 및 FixedSizeOf가 정의 요소에 대해, 우리는 향상된 성능을 얻을.
사건의 나머지 부분에서는 컬렉션을 통해 이동 및 개별 크기를 요약.
내 문제는 길이와 접이식 모두가 컨테이너에 대해 정의 된 경우이며, FixedSizeOf은 요소에 대한 정의된다. 이 여기에 매우 일반적인 경우입니다 (예를 들어, :. 목록 [지능]는 모두 정의가).
예:
scala> implicitly[SizeOf[List[Int]]].sizeOf(List(1,2,3))
<console>:24: error: ambiguous implicit values:
both method foldSizeOf of type [T[_], A](implicit evidence$1: scalaz.Foldable[T], implicit evidence$2: SizeOf[A])VarSizeOf[T[A]]
and method fixedSizeOf of type [T[_], A](implicit evidence$1: scalaz.Length[T], implicit evidence$2: FixedSizeOf[A])VarSizeOf[T[A]]
match expected type SizeOf[List[Int]]
implicitly[SizeOf[List[Int]]].sizeOf(List(1,2,3))
내가하고 싶은 것은 길이 + FixedSizeOf 조합이 적용되지 않는 경우에만 접이식 타입 클래스에 의존 할 수있다.
이를 위해, 나는 VarSizeOf 요소를 받아 foldSizeOf ()의 정의를 변경할 수 있습니다 :
implicit def foldSizeOfVar[T[_] : Foldable, A : VarSizeOf] = // ...
그리고 지금 우리 FixedSizeOf 요소와 정의 된 길이 접이식 컨테이너를 다루고 문제가있는 부분을 작성해야합니다. 나는이 접근하는 방법을 잘 모르겠지만, 의사 코드는 같을 것이다 :
implicit def foldSizeOfFixed[T[_] : Foldable : Not[Length], A : FixedSizeOf] = // ...
'하지 않음 [길이], 분명히, 여기에 만들어 일부를 제공합니다.
내가 알고 있는데 일부 솔루션
1) 낮은 우선 순위 implicits 대한 클래스를 정의와 '객체가 PREDEF LowPriorityImplicits 확장'에 도시 된 바와 같이, 그것을 확장한다. 마지막 암시 (foldSizeOfFixed ()) 상위 클래스에 정의 할 수 있고, 자손 클래스에서 다른 오버라이드 (override) 할 것입니다.
나는 결국 인 SizeOf의 재귀 적 사용을 지원할 수 있도록하고 싶습니다 때문에이 옵션에 관심이 아니에요, 이것은 (내 올바른 여기 이해하는 하위 클래스들에 의존에서 낮은 우선 순위 기본 클래스에서 암시를 방지 할 수 있습니다? 편집 :! 잘못 하위 클래스의 컨텍스트에서 암시 조회 작업이 실행 가능한 솔루션입니다)!
2) 거친 접근 방식은 옵션에 의존이다 TypeClass (예를 들어, : 옵션 [길이 [목록]]. 그 중 몇 난 그냥 암시 하나의 큰 팔자 '를 쓸 수 필수 및 길이와 FixedSizeOf로 추천 접이식 및 인 SizeOf 옵션, 그리고 그들이 사용할 수있는 경우 후자에 의존한다 (출처 : 여기).
아무 관련 타입 클래스 인스턴스가 위치한 수없는 경우에 여기에서 두 가지 문제는 모듈화의 부족 및 런타임 예외 떨어지는 돌아 (이 예는 아마이 솔루션과 함께 작업을 할 수 있지만 항상 가능한 것은 아니다)
편집 : 이것은 내가 선택 implicits으로 얻을 수있었습니다 최고입니다. 그것은 아직 아니다 :
implicit def optionalTypeClass[TC](implicit tc: TC = null) = Option(tc)
type OptionalLength[T[_]] = Option[Length[T]]
type OptionalFixedSizeOf[T[_]] = Option[FixedSizeOf[T]]
implicit def sizeOfContainer[
T[_] : Foldable : OptionalLength,
A : SizeOf : OptionalFixedSizeOf]: SizeOf[T[A]] = new SizeOf[T[A]] {
def sizeOf(as: T[A]) = {
// optionally calculate using Length + FixedSizeOf is possible
val fixedLength = for {
lengthOf <- implicitly[OptionalLength[T]]
sizeOf <- implicitly[OptionalFixedSizeOf[A]]
} yield lengthOf.length(as) * sizeOf.fixedSize
// otherwise fall back to Foldable
fixedLength.getOrElse {
val foldable = implicitly[Foldable[T]]
val sizeOf = implicitly[SizeOf[A]]
foldable.foldMap(as)(a => sizeOf.sizeOf(a))
}
}
}
여전히 필요하다, 이전부터 fixedSizeOf ()이 충돌을 예외입니다.
어떤 도움이나 관점을 주셔서 감사합니다 :-)
해결법
-
==============================
1.나는 결국 상속을 사용하여 우선 순위를 필요로하지 않는 모호성 기반 솔루션을 사용하여이 문제를 해결했다.
나는 결국 상속을 사용하여 우선 순위를 필요로하지 않는 모호성 기반 솔루션을 사용하여이 문제를 해결했다.
다음은이 일반화에서 내 시도이다.
우리는 네거티브 형 클래스를 구성 할 수 없음 [A] 유형을 사용 :
import scala.language.higherKinds trait Not[A] trait Monoid[_] // or import scalaz._, Scalaz._ type NotMonoid[A] = Not[Monoid[A]] trait Functor[_[_]] // or import scalaz._, Scalaz._ type NotFunctor[M[_]] = Not[Functor[M]]
... 다음 상황에 맞는 범위로 사용할 수있다 :
def foo[T: NotMonoid] = ...
우리는하지 않음 [A]의 모든 유효한 식는 적어도 하나 개의 암시 적 인스턴스를 얻을 것이라는 점을 보장하여 진행합니다.
implicit def notA[A, TC[_]] = new Not[TC[A]] {}
인스턴스는 'NOTA'라고 - '하지'가있는 경우에만 인스턴스를 찾을 때문에 '하지 않음 [TC [A]]'그 부정적인 유형 클래스를 적용 발견; 'A'는 통상의 방법에 대해 첨부되는 평면 형상의 종류 (예를 들면 int)를 다룬다.
우리는 지금 원하지 않는 종류의 클래스가 적용되는 경우를 외면하는 모호성을 소개 :
implicit def notNotA[A : TC, TC[_]] = new Not[TC[A]] {}
우리는 'TC'로 지정 유형 클래스의 인스턴스가 암시 적 범위에 존재하는 유형에 관심이 여기에 제외 이것은 거의 정확하게 'NOTA'과 동일합니다. 인스턴스는 단지 암시 적 존재가 고개를 일치하여 이후, 'notNotA'라는 이름, 그것은 (우리의 목표입니다) 암시 적 검색을 실패 'NOTA'와 함께 모호성을 만듭니다.
의는 사용 예를 통해 가자. 우리는 위에서 'NotMonoid'네거티브 형 클래스를 사용합니다 :
implicitly[NotMonoid[java.io.File]] // succeeds implicitly[NotMonoid[Int]] // fails def showIfNotMonoid[A: NotMonoid](a: A) = a.toString showIfNotMonoid(3) // fails, good! showIfNotMonoid(scala.Console) // succeeds for anything that isn't a Monoid
여태까지는 그런대로 잘됐다! 그러나, 유형 M [_]을 형성하고 입력 클래스 [_ [_] TC 위의 방식에 의해 현재 지원되지 않는 형상. 의뿐만 아니라 그들을 위해 implicits를 추가 할 수 있습니다 :
implicit def notM[M[_], TC[_[_]]] = new Not[TC[M]] {} implicit def notNotM[M[_] : TC, TC[_[_]]] = new Not[TC[M]] {} implicitly[NotFunctor[List]] // fails implicitly[NotFunctor[Class]] // succeeds
간단한 충분. 모양을 '적용 취소'에 대한 - Scalaz 여러 종류의 모양을 취급으로 인한 보일러에 대한 해결 방법을 가지고 있습니다. 나는 그것이 마치 마법처럼 TC [_ [_] (예를 들면은 Functor)에 근무하더라도 (예 : 모노 이드와 같은 모양 TC [_]의 형태 클래스) 기본 경우에 그것의 사용을 할 수 없었다 그래서이 답변은 적용되지 않습니다.
아무도 관심이 있다면, 여기의 모든 것이 하나의 코드에서 필요한 :
import scala.language.higherKinds trait Not[A] object Not { implicit def notA[A, TC[_]] = new Not[TC[A]] {} implicit def notNotA[A : TC, TC[_]] = new Not[TC[A]] {} implicit def notM[M[_], TC[_[_]]] = new Not[TC[M]] {} implicit def notNotM[M[_] : TC, TC[_[_]]] = new Not[TC[M]] {} } import Not._ type NotNumeric[A] = Not[Numeric[A]] implicitly[NotNumeric[String]] // succeeds implicitly[NotNumeric[Int]] // fails
나는이 문제에 대한 질문 의사 코드 때문에 (실제 코드)과 같을 것이다 :
// NotFunctor[M[_]] declared above def notFunctor[M[_] : NotFunctor](m: M[_]) = s"$m is not a functor"
업데이트 : 유사 기술은 암시 적 변환에 적용 :
import scala.language.higherKinds trait Not[A] object Not { implicit def not[V[_], A](a: A) = new Not[V[A]] {} implicit def notNot[V[_], A <% V[A]](a: A) = new Not[V[A]] {} }
우리는 지금 (예를 들어) 순서가 그들의 유형을 볼 수없는 경우에만 가치를 인정하는 함수를 정의 할 수 있습니다 :
def unordered[A <% Not[Ordered[A]]](a: A) = a
from https://stackoverflow.com/questions/15962743/using-context-bounds-negatively-to-ensure-type-class-instance-is-absent-from-s by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 왜 HDFS에 대한 한계는 2GB 스파크 RDD 파티션이 무엇입니까? (0) | 2019.11.12 |
---|---|
[SCALA] 스파크 RDD의 foreach는 내부 수정 수집 (0) | 2019.11.12 |
[SCALA] 재생의 전류 루프의 인덱스를 가져 오기! 2 스칼라 템플릿 (0) | 2019.11.12 |
[SCALA] 병렬 스칼라 평행 모음 정도 (0) | 2019.11.12 |
[SCALA] 자바에서 스칼라를 사용하여 다음 매개 변수로 함수를 전달 (0) | 2019.11.12 |