[SCALA] 방법 "형 분리"(노동 조합 유형)를 정의 하는가?
SCALA방법 "형 분리"(노동 조합 유형)를 정의 하는가?
오버로드 된 메서드의 두 정의를 처리하기 위해 제안 된 방법 중 하나는 패턴 매칭에 과부하를 대체하는 것입니다 :
object Bar {
def foo(xs: Any*) = xs foreach {
case _:String => println("str")
case _:Int => println("int")
case _ => throw new UglyRuntimeException()
}
}
이 방법은 우리가 foo에 대한 인수의 정적 유형 검사를 포기해야합니다. 쓸 수 있도록 훨씬 더 좋은 것
object Bar {
def foo(xs: (String or Int)*) = xs foreach {
case _: String => println("str")
case _: Int => println("int")
}
}
나는 어느 쪽과 가까이 할 수 있지만, 두 개 이상의 종류의 빠른 추한 가져옵니다
type or[L,R] = Either[L,R]
implicit def l2Or[L,R](l: L): L or R = Left(l)
implicit def r2Or[L,R](r: R): L or R = Right(r)
object Bar {
def foo(xs: (String or Int)*) = xs foreach {
case Left(l) => println("str")
case Right(r) => println("int")
}
}
그것은 일반적인 Either3이 Either4는 ... 사람이 같은 목적을 달성하기 위해 다른 솔루션을 알고 있나요 정의 필요 (우아하고, 효율적인) 솔루션처럼 보인다? 제가 알기로, 스칼라는 내장 된 "유형 분리"를 가지고 있지 않습니다. 또한, 난 그냥 가져올 수 있도록 어딘가에 표준 라이브러리에 숨어 위에서 정의 된 암시 적 변환은?
해결법
-
==============================
1.이 혼합 유형을 허용하지 않습니다뿐만 아니라 모든 *의 특정한 경우에,이 트릭은 아래 작동하지 않습니다. 혼합 유형 중 하나를 오버로드와 함께 작동하지 않을 것입니다 때문에, 이것은 당신이 원하는 것을 할 수있다.
이 혼합 유형을 허용하지 않습니다뿐만 아니라 모든 *의 특정한 경우에,이 트릭은 아래 작동하지 않습니다. 혼합 유형 중 하나를 오버로드와 함께 작동하지 않을 것입니다 때문에, 이것은 당신이 원하는 것을 할 수있다.
먼저, 다음과 같이 동의 할 유형을 가진 클래스를 선언 :
class StringOrInt[T] object StringOrInt { implicit object IntWitness extends StringOrInt[Int] implicit object StringWitness extends StringOrInt[String] }
다음과 같은 foo는 선언 :
object Bar { def foo[T: StringOrInt](x: T) = x match { case _: String => println("str") case _: Int => println("int") } }
그리고 그게 다야. 당신은 foo는 (5) 또는 foo는 ( "ABC")를 호출 할 수 있습니다, 그것은 작동하지만 foo는 (true)를 시도하고 실패합니다. 아래 랜달에 의해 언급 된 바와 같이, 당신은 StringOrInt 봉인 클래스하지 않는 한이, 사이드 스텝 클라이언트 코드에 의해 StringOrInt [부울]를 작성하여이 될 수 있습니다.
StringOrInt 형 StringOrInt의 암시 적 매개 변수 [T]를 거기에 의미하고, 스칼라 유형의 동반자 객체 내부에 보이기 때문에 해당 유형의 작업을 요청하는 코드를 만들 수있다 implicits이 있는지 : 그것은 T가 있기 때문에 작동합니다.
-
==============================
2.마일 사빈은 카레 - 하워드의 동형를 통해 스칼라에있는 그의 최근 블로그 포스트 박스 없음 노조 종류의 조합 유형을 얻을 수있는 아주 좋은 방법을 설명합니다 :
마일 사빈은 카레 - 하워드의 동형를 통해 스칼라에있는 그의 최근 블로그 포스트 박스 없음 노조 종류의 조합 유형을 얻을 수있는 아주 좋은 방법을 설명합니다 :
그는 처음으로 유형의 부정을 정의
type ¬[A] = A => Nothing
드 모건의 법칙을 사용하여이 그를 노동 조합 유형을 정의 할 수 있습니다
type ∨[T, U] = ¬[¬[T] with ¬[U]]
다음으로, 보조 구조체
type ¬¬[A] = ¬[¬[A]] type |∨|[T, U] = { type λ[X] = ¬¬[X] <:< (T ∨ U) }
다음과 같이 노동 조합 유형을 작성할 수 있습니다 :
def size[T : (Int |∨| String)#λ](t : T) = t match { case i : Int => i case s : String => s.length }
-
==============================
3.: 당신은 당신이 원하는 정확히 무엇을 할 수 있도록, | (B 작성된 A) 도티, 새로운 실험 스칼라 컴파일러는, 노동 조합 유형을 지원합니다
: 당신은 당신이 원하는 정확히 무엇을 할 수 있도록, | (B 작성된 A) 도티, 새로운 실험 스칼라 컴파일러는, 노동 조합 유형을 지원합니다
def foo(xs: (String | Int)*) = xs foreach { case _: String => println("str") case _: Int => println("int") }
-
==============================
4.여기에 노동 조합 유형을 인코딩 할 수있는 렉스 커의 방법입니다. 직선과 간단한!
여기에 노동 조합 유형을 인코딩 할 수있는 렉스 커의 방법입니다. 직선과 간단한!
scala> def f[A](a: A)(implicit ev: (Int with String) <:< A) = a match { | case i: Int => i + 1 | case s: String => s.length | } f: [A](a: A)(implicit ev: <:<[Int with String,A])Int scala> f(3) res0: Int = 4 scala> f("hello") res1: Int = 5 scala> f(9.2) <console>:9: error: Cannot prove that Int with String <:< Double. f(9.2) ^
출처 : 스칼라에서 노동 조합 유형을 인코딩하는 또 다른 방법을 제공 마일 사빈에 의해이 우수한 블로그 게시물에서 # 27 코멘트.
-
==============================
5.그것은 다음과 같이 다니엘의 솔루션을 일반화 할 수있다 :
그것은 다음과 같이 다니엘의 솔루션을 일반화 할 수있다 :
sealed trait Or[A, B] object Or { implicit def a2Or[A,B](a: A) = new Or[A, B] {} implicit def b2Or[A,B](b: B) = new Or[A, B] {} } object Bar { def foo[T <% String Or Int](x: T) = x match { case _: String => println("str") case _: Int => println("int") } }
이 방법의 가장 큰 단점은
최신 정보:
미치 블레 빈스는 매우 유사한 접근 방식을 설명하고 그것에게 "말더듬 또는"더빙, 이상의 두 가지 유형으로 일반화하는 방법을 보여줍니다.
-
==============================
6.나는 종류의 사람이 다른 답변에서 언급이 지역에서 마일 사빈의 작업의 단순화와 유형 목록의 개념을 결합하여 n 차 노조 종류의 비교적 깨끗한 구현을 발견했다.
나는 종류의 사람이 다른 답변에서 언급이 지역에서 마일 사빈의 작업의 단순화와 유형 목록의 개념을 결합하여 n 차 노조 종류의 비교적 깨끗한 구현을 발견했다.
지정된 타입 ¬ [-A] 정의하여 <부여하는 contravariant에있는 우리가 쓸 수 B를 ¬ [B] : <¬ [A]의 종류 순서를 반전.
주어 종류 A, B, X는, 우리는 X <표현하려면, • || X <: B. ¬ [X] || : contravariance를 적용, 우리는 ¬ [A] <를 얻을 수 ¬ [B] : <¬ [X]. 이것은 차례로 수 (A)의 하나 또는 B가 X 또는 X 자체의 슈퍼되어야하는 ¬ [X]를 (함수 인수 생각해) [A] ¬ [B]와 <¬ 같이 표현 될 수있다.
object Union { import scala.language.higherKinds sealed trait ¬[-A] sealed trait TSet { type Compound[A] type Map[F[_]] <: TSet } sealed trait ∅ extends TSet { type Compound[A] = A type Map[F[_]] = ∅ } // Note that this type is left-associative for the sake of concision. sealed trait ∨[T <: TSet, H] extends TSet { // Given a type of the form `∅ ∨ A ∨ B ∨ ...` and parameter `X`, we want to produce the type // `¬[A] with ¬[B] with ... <:< ¬[X]`. type Member[X] = T#Map[¬]#Compound[¬[H]] <:< ¬[X] // This could be generalized as a fold, but for concision we leave it as is. type Compound[A] = T#Compound[H with A] type Map[F[_]] = T#Map[F] ∨ F[H] } def foo[A : (∅ ∨ String ∨ Int ∨ List[Int])#Member](a: A): String = a match { case s: String => "String" case i: Int => "Int" case l: List[_] => "List[Int]" } foo(42) foo("bar") foo(List(1, 2, 3)) foo(42d) // error foo[Any](???) // error }
그러나 나는 형의 경계를 가지는지도의 구현은 지금까지 도전 입증했다,하라 / 최대의 TLists에서 볼 수 있듯이 멤버 유형을 상한으로이 아이디어를 결합하려고 시간을 보내고 있었다.
-
==============================
7.A 형 클래스 솔루션은 아마 implicits를 사용하여, 여기에 갈 수있는 좋은 방법입니다. 이것은 Odersky / 스푼 / Venners 책에서 언급 된 모노 이드 방식과 유사합니다 :
A 형 클래스 솔루션은 아마 implicits를 사용하여, 여기에 갈 수있는 좋은 방법입니다. 이것은 Odersky / 스푼 / Venners 책에서 언급 된 모노 이드 방식과 유사합니다 :
abstract class NameOf[T] { def get : String } implicit object NameOfStr extends NameOf[String] { def get = "str" } implicit object NameOfInt extends NameOf[Int] { def get = "int" } def printNameOf[T](t:T)(implicit name : NameOf[T]) = println(name.get)
그런 다음 REPL이 실행하는 경우 :
scala> printNameOf(1) int scala> printNameOf("sss") str scala> printNameOf(2.0f) <console>:10: error: could not find implicit value for parameter nameOf: NameOf[ Float] printNameOf(2.0f) ^
-
==============================
8.우리는 유형 운영자 또는 싶습니다 [U, V]와 같은 방식으로 형식 매개 변수 X를 제한하는 데 사용할 수있는 그 중 X <: U 또는 X <: V. 여기에 우리가 할 수있는만큼 거의 가깝게 정의의 가져 오기:
우리는 유형 운영자 또는 싶습니다 [U, V]와 같은 방식으로 형식 매개 변수 X를 제한하는 데 사용할 수있는 그 중 X <: U 또는 X <: V. 여기에 우리가 할 수있는만큼 거의 가깝게 정의의 가져 오기:
trait Inv[-X] type Or[U,T] = { type pf[X] = (Inv[U] with Inv[T]) <:< Inv[X] }
여기가 사용되는 방법입니다 :
// use class A; class B extends A; class C extends B def foo[X : (B Or String)#pf] = {} foo[B] // OK foo[C] // OK foo[String] // OK foo[A] // ERROR! foo[Number] // ERROR!
이 작업은 몇 스칼라 유형의 트릭을 사용합니다. 메인 하나는 일반화 된 형태 제약의 사용이다. 주어 종류의 U와 V는 스칼라 컴파일러는 U라는 클래스를 제공한다 <
def foo[X](implicit ev : (B with String) <:< X) = {}
이 예는 클래스 B, 문자열의 경우 X 인스턴스를 작동, 또는 슈퍼 나 B 또는 문자열의 하위 유형도 아닌 유형이 있습니다. B와 (문자열과 B) <: : 문자열, 그래서 스칼라는 EV로 전달되는 암시 적 객체를 제공합니다 : 처음 두 경우에, 키워드 (문자열과 B) <로의 정의에 의해 사실 년대 스칼라 컴파일러는 제대로 foo는 [B]와 foo는 [문자열]을 받아 들일 것입니다.
X, 다음 U는 <: 마지막 경우에, 나는 V <와 U이 경우는 사실에 의존하고있어 X 또는 V <: X. 그것은 직관적으로 진실 것, 그리고 단순히 그것을 믿고있어. X가 퍼 유형 또는 하위 유형 인 경우이 간단한 예제가 실패 이유는이 가정에서 분명 하나 B 또는 문자열 : 예를 들어, 위의 예에서, foo는이 [A] 잘못 인정하고 foo는 [C]가 잘못 거부됩니다. U 또는 X <: V. 다시 말하지만, 우리가 원하는 것은 정확히 X <사실 일부 변수 U, V에 입력 한 표현의 종류 및 X는
contravariance의 스칼라의 개념은 여기에 도움이 될 수 있습니다. 형질의 특성 인보이스 [-X]를 기억 하는가? 그것의 입력 파라미터 X, 인보이스 [X]에서
trait Inv[-X] def foo[X](implicit ev : (Inv[B] with Inv[String]) <:< Inv[X]) = {}
즉,이기 때문에 식 <(인보이스 [U] 인보이스 [V]로) 인보이스는 [X]가, 위와 같은 가정에서, 사실 정확히 인보이스 [U] <: 인보이스 [X] 또는 인보이스 [V] : <인보이스 [X] 및 contravariance 정의함으로써, 이것이 사실 정확히 X <: U 또는 X <: V.
그것은 parametrizable 형 BOrString [X]를 선언하고 다음과 같이 사용하여 일을 좀 더 재사용 할 수있다 :
trait Inv[-X] type BOrString[X] = (Inv[B] with Inv[String]) <:< Inv[X] def foo[X](implicit ev : BOrString[X]) = {}
스칼라는 이제 호출 될 때마다 X가 foo에 대한 형식 BOrString [X]를 구성하려고 시도하고 유형은 X가 B 또는 문자열 중 하나의 하위 유형입니다 정확히 때 구성됩니다. 즉 작동하고, 속기 표기법이있다. (즉, EV가 이제있어서 본문에 참조해야 제외 암묵적 [BOrString [X]보다는 단순히 EV) 아래 구문은 동일하며 결합 된 형태로 BOrString 컨텍스트를 사용
def foo[X : BOrString] = {}
우리가 정말 원하는 것은 바인딩 유형 컨텍스트를 만들 수있는 유연한 방법입니다. A 형 컨텍스트는 parametrizable 유형이어야합니다, 우리는 parametrizable 방법은 하나를 만들려고합니다. 우리는 우리가 값 기능을 카레처럼 유형의 기능을 카레하려는 것처럼 그 소리. 즉, 우리는 다음과 같은 일을하고 싶습니다 :
type Or[U,T][X] = (Inv[U] with Inv[T]) <:< Inv[X]
즉 스칼라에서 직접 불가능합니다,하지만 우리는 매우 가까이하는 데 사용할 수있는 트릭이있다. 즉의 또는 위의 정의에 우리를 제공합니다 :
trait Inv[-X] type Or[U,T] = { type pf[X] = (Inv[U] with Inv[T]) <:< Inv[X] }
여기에서 우리는 구조 유형 또는 하나 개의 내부 유형이 보장 [U, T]를 만들 구조 입력 및 스칼라의 파운드 연산자를 사용합니다. 이 이상한 짐승이다. 일부 내용을 제공하기 위해, 함수 DEF 바 [X <{타입 Y = 지능}] (X : X) = {}는 Y는 그 안에 정의 된 유형을 가지고 AnyRef 서브 호출해야 :
bar(new AnyRef{ type Y = Int }) // works!
파운드 연산자를 사용하여 우리가 foo는 우리의 원래 정의에 도착, 우리가 유형 연산자의 내부 입력하거나 [B, 문자열] #pf 및 사용 중위 표기를 참조 할 수 있습니다 또는 :
def foo[X : (B Or String)#pf] = {}
우리는 기능 유형이 특성 인보이스를 정의 피하기 위해 자신의 첫 번째 유형 매개 변수에 contravariant 있다는 사실을 사용할 수 있습니다 :
type Or[U,T] = { type pf[X] = ((U => _) with (T => _)) <:< (X => _) }
-
==============================
9.이 해킹도 있습니다 :
이 해킹도 있습니다 :
implicit val x: Int = 0 def foo(a: List[Int])(implicit ignore: Int) { } implicit val y = "" def foo(a: List[String])(implicit ignore: String) { } foo(1::2::Nil) foo("a"::"b"::Nil)
타입 삭제 모호성 (스칼라) 주위 작업을 참조하십시오.
-
==============================
10.당신은 OneOf라는 뭔가가 MetaScala, 한 번 봐 걸릴 수 있습니다. 나는이 일치 문 잘 작동하지 않습니다하지만 당신은 고차 함수를 사용하여 매칭을 시뮬레이션 할 수 있다는 인상을받을. 꽤 아직 작동하지 않습니다 아마도 때문에, 예를 들어, 가져온 부분을 살펴 보자하지만, "모의 일치"부분이 주석 있습니다.
당신은 OneOf라는 뭔가가 MetaScala, 한 번 봐 걸릴 수 있습니다. 나는이 일치 문 잘 작동하지 않습니다하지만 당신은 고차 함수를 사용하여 매칭을 시뮬레이션 할 수 있다는 인상을받을. 꽤 아직 작동하지 않습니다 아마도 때문에, 예를 들어, 가져온 부분을 살펴 보자하지만, "모의 일치"부분이 주석 있습니다.
이제 몇 가지 editorializing을 위해 : 나는 당신이 설명하는대로 등 Either3, Either4을, 정의에 대한 지독한 거기에 아무것도 생각하지 않습니다. 이 스칼라에 내장 된 표준 (22) 튜플 타입에 기본적으로 듀얼입니다. 그것은 확실히 스칼라 내장 한 경우 논리합 종류의 좋은, 그리고 것 아마도 {X, Y, Z} 같은 그들에 대한 몇 가지 좋은 구문.
-
==============================
11.나는이 다른 아형에 분리의 원하는 유형의에 / 대체 부속 유형 및 암시 적 변환으로, 첫 번째 클래스 분리 된 형태가 봉인 된 상위 유형이라고 생각하고있다.
나는이 다른 아형에 분리의 원하는 유형의에 / 대체 부속 유형 및 암시 적 변환으로, 첫 번째 클래스 분리 된 형태가 봉인 된 상위 유형이라고 생각하고있다.
나는이 댓글 (33) 주소 가정 - 마일 사빈의 솔루션의 36을, 그래서 사용하는 사이트에서 사용할 수있다 첫 번째 클래스 유형이,하지만 난 그것을 테스트하지 않았다.
sealed trait IntOrString case class IntOfIntOrString( v:Int ) extends IntOrString case class StringOfIntOrString( v:String ) extends IntOrString implicit def IntToIntOfIntOrString( v:Int ) = new IntOfIntOrString(v) implicit def StringToStringOfIntOrString( v:String ) = new StringOfIntOrString(v) object Int { def unapply( t : IntOrString ) : Option[Int] = t match { case v : IntOfIntOrString => Some( v.v ) case _ => None } } object String { def unapply( t : IntOrString ) : Option[String] = t match { case v : StringOfIntOrString => Some( v.v ) case _ => None } } def size( t : IntOrString ) = t match { case Int(i) => i case String(s) => s.length } scala> size("test") res0: Int = 4 scala> size(2) res1: Int = 2
지능 : 하나의 문제는 스칼라가 아닌 경우 난의 경우 일치하는 맥락 지능 (및 문자열에 StringOfIntOrString)에 IntOfIntOrString에서 암시 적 변환에 사용하지 않으므로 추출기를 정의하고 경우 지능 (i)를 사용해야합니다.
ADD : 다음과 같이 내가 자신의 블로그에서 마일 사빈에 반응했다. 아마 어느 비해 몇 가지 개선 사항이 있습니다 :
UPDATE : 위의 패턴에 대한 분리의 논리 부정 다음, 나는 마일 사빈의 블로그에서 대안 (아마도 더 유용) 패턴을 추가했다.
sealed trait `Int or String` sealed trait `not an Int or String` sealed trait `Int|String`[T,E] case class `IntOf(Int|String)`( v:Int ) extends `Int|String`[Int,`Int or String`] case class `StringOf(Int|String)`( v:String ) extends `Int|String`[String,`Int or String`] case class `NotAn(Int|String)`[T]( v:T ) extends `Int|String`[T,`not an Int or String`] implicit def `IntTo(IntOf(Int|String))`( v:Int ) = new `IntOf(Int|String)`(v) implicit def `StringTo(StringOf(Int|String))`( v:String ) = new `StringOf(Int|String)`(v) implicit def `AnyTo(NotAn(Int|String))`[T]( v:T ) = new `NotAn(Int|String)`[T](v) def disjunction[T,E](x: `Int|String`[T,E])(implicit ev: E =:= `Int or String`) = x def negationOfDisjunction[T,E](x: `Int|String`[T,E])(implicit ev: E =:= `not an Int or String`) = x scala> disjunction(5) res0: Int|String[Int,Int or String] = IntOf(Int|String)(5) scala> disjunction("") res1: Int|String[String,Int or String] = StringOf(Int|String)() scala> disjunction(5.0) error: could not find implicit value for parameter ev: =:=[not an Int or String,Int or String] disjunction(5.0) ^ scala> negationOfDisjunction(5) error: could not find implicit value for parameter ev: =:=[Int or String,not an Int or String] negationOfDisjunction(5) ^ scala> negationOfDisjunction("") error: could not find implicit value for parameter ev: =:=[Int or String,not an Int or String] negationOfDisjunction("") ^ scala> negationOfDisjunction(5.0) res5: Int|String[Double,not an Int or String] = NotAn(Int|String)(5.0)
ANOTHER UPDATE : 주석 23 마일 사빈의 솔루션의 35에 관해서는, 여기에 사용 현장에서 노동 조합 유형을 선언하는 방법입니다. 그것이 첫 번째 수준 후 언 박싱 참고 즉 어느 중첩 권투를 필요로하고 내 이전의 코멘트 (41)의 패러다임이 확장하지 않았다 반면이의 분리의 유형의 수에 확장되는 장점이있다. 즉, D [지능 ∨ 문자열 (즉의 서브 타입 임) D [지능 ∨ ∨ 문자열 더블]에 할당된다.
type ¬[A] = (() => A) => A type ∨[T, U] = ¬[T] with ¬[U] class D[-A](v: A) { def get[T](f: (() => T)) = v match { case x : ¬[T] => x(f) } } def size(t: D[Int ∨ String]) = t match { case x: D[¬[Int]] => x.get( () => 0 ) case x: D[¬[String]] => x.get( () => "" ) case x: D[¬[Double]] => x.get( () => 0.0 ) } implicit def neg[A](x: A) = new D[¬[A]]( (f: (() => A)) => x ) scala> size(5) res0: Any = 5 scala> size("") error: type mismatch; found : java.lang.String("") required: D[?[Int,String]] size("") ^ scala> size("hi" : D[¬[String]]) res2: Any = hi scala> size(5.0 : D[¬[Double]]) error: type mismatch; found : D[(() => Double) => Double] required: D[?[Int,String]] size(5.0 : D[?[Double]]) ^
분명히 스칼라 컴파일러는 세 가지 버그가 있습니다.
3.
scala> class D[-A](v: A) { def get[T](f: (() => T))(implicit e: A <:< ¬[T]) = v match { case x : ¬[T] => x(f) } } error: contravariant type A occurs in covariant position in type <:<[A,(() => T) => T] of value e def get[T](f: (() => T))(implicit e: A <:< ?[T]) = v match { ^
컴파일러는 공변 위치에 허용하지 않습니다 때문에 get 메소드는 입력 종류에 적절하게 제한되지 않습니다. 하나는 우리가 이제까지 기능에 증거 액세스하지 않습니다, 우리가 원하는 모든 증거이기 때문에 그 버그 주장 할 수 있습니다. 그리고이 선택은 get 메소드에서 _ 경우를 테스트하지 만든, 그래서 크기의 경기에서 옵션을 언 박싱 할 필요가 없습니다 것입니다 ().
2012년 3월 5일는 : 선행 업데이트는 개선이 필요합니다. 마일 사빈의 솔루션은 하위 유형으로 제대로했다.
type ¬[A] = A => Nothing type ∨[T, U] = ¬[T] with ¬[U] class Super class Sub extends Super scala> implicitly[(Super ∨ String) <:< ¬[Super]] res0: <:<[?[Super,String],(Super) => Nothing] = scala> implicitly[(Super ∨ String) <:< ¬[Sub]] res2: <:<[?[Super,String],(Sub) => Nothing] = scala> implicitly[(Super ∨ String) <:< ¬[Any]] error: could not find implicit value for parameter e: <:<[?[Super,String],(Any) => Nothing] implicitly[(Super ? String) <:< ?[Any]] ^
(근처 일류 조합 유형에 대한) 내 이전에 갱신의 제안은 하위 유형을 끊었다.
scala> implicitly[D[¬[Sub]] <:< D[(Super ∨ String)]] error: could not find implicit value for parameter e: <:<[D[(() => Sub) => Sub],D[?[Super,String]]] implicitly[D[?[Sub]] <:< D[(Super ? String)]] ^
문제는 한 위치, 따라서 대체 (함수 입력 기능의 입력 또는 기능이 경우의 리턴 값)이 (() => A)에서 A => A는 공변 (복귀 형) 모두에 나타나며 contravariant이고 유일한 불변 일 수있다.
우리가 contravariant 위치에 원하는에만 때문에의 슈퍼 타입이 D의 아형이되지 않도록, 즉 A => 아무것도 필요하지 않습니다 참고 [¬에게 [A]는]도 D [¬에게 [A] ¬로 [U]를 (또한 참조 ). 우리는 이중 contravariance을 필요로하기 때문에 우리가 ¬ 및 ∨을 폐기 할 경우에도, 우리는 마일 '솔루션에 해당 얻을 수 있습니다.
trait D[-A] scala> implicitly[D[D[Super]] <:< D[D[Super] with D[String]]] res0: <:<[D[D[Super]],D[D[Super] with D[String]]] = scala> implicitly[D[D[Sub]] <:< D[D[Super] with D[String]]] res1: <:<[D[D[Sub]],D[D[Super] with D[String]]] = scala> implicitly[D[D[Any]] <:< D[D[Super] with D[String]]] error: could not find implicit value for parameter e: <:<[D[D[Any]],D[D[Super] with D[String]]] implicitly[D[D[Any]] <:< D[D[Super] with D[String]]] ^
그래서 전체 수정입니다.
class D[-A] (v: A) { def get[T <: A] = v match { case x: T => x } } implicit def neg[A](x: A) = new D[D[A]]( new D[A](x) ) def size(t: D[D[Int] with D[String]]) = t match { case x: D[D[Int]] => x.get[D[Int]].get[Int] case x: D[D[String]] => x.get[D[String]].get[String] case x: D[D[Double]] => x.get[D[Double]].get[Double] }
T는 현재 A의 하위 유형으로 제한됩니다로 스칼라가 남아있는 이전이 버그를 참고하지만, 3 일을 피할 수있다
우리는 하위 유형의 작품을 확인할 수 있습니다.
def size(t: D[D[Super] with D[String]]) = t match { case x: D[D[Super]] => x.get[D[Super]].get[Super] case x: D[D[String]] => x.get[D[String]].get[String] } scala> size( new Super ) res7: Any = Super@1272e52 scala> size( new Sub ) res8: Any = Sub@1d941d7
나는 두 실론을 가지고있는 이유로, 일류 교차 유형이 매우 중요하다고 생각되었습니다 때문에 대신 모든있는에 subsuming의 이종 (런타임 오류를 생성 할 수 있습니다 예상 유형에 일치하는의 언 박싱과 언 박싱 의미 a) 분리를 포함하는 컬렉션은 스칼라 타입이 I 기록한 버그)을 수정한다 (확인할 수있다. 조합 이종 컬렉션에 대해 metascala의 실험 HList 사용의 복잡성보다 더 간단하다.
-
==============================
12.당신은 카레 - 하워드을 grok 수없는 경우 이해하기 조금 쉽게하는 또 다른 방법이있다 :
당신은 카레 - 하워드을 grok 수없는 경우 이해하기 조금 쉽게하는 또 다른 방법이있다 :
type v[A,B] = Either[Option[A], Option[B]] private def L[A,B](a: A): v[A,B] = Left(Some(a)) private def R[A,B](b: B): v[A,B] = Right(Some(b)) // TODO: for more use scala macro to generate this for up to 22 types? implicit def a2[A,B](a: A): v[A,B] = L(a) implicit def b2[A,B](b: B): v[A,B] = R(b) implicit def a3[A,B,C](a: A): v[v[A,B],C] = L(a2(a)) implicit def b3[A,B,C](b: B): v[v[A,B],C] = L(b2(b)) implicit def a4[A,B,C,D](a: A): v[v[v[A,B],C],D] = L(a3(a)) implicit def b4[A,B,C,D](b: B): v[v[v[A,B],C],D] = L(b3(b)) implicit def a5[A,B,C,D,E](a: A): v[v[v[v[A,B],C],D],E] = L(a4(a)) implicit def b5[A,B,C,D,E](b: B): v[v[v[v[A,B],C],D],E] = L(b4(b)) type JsonPrimtives = (String v Int v Double) type ValidJsonPrimitive[A] = A => JsonPrimtives def test[A : ValidJsonPrimitive](x: A): A = x test("hi") test(9) // test(true) // does not compile
나는 디종에서 유사한 기술을 사용하여
-
==============================
13.글쎄, 그건 모두 아주 영리,하지만 난 당신이 이미 주요 질문에 대한 대답은 "아니오"의 다양한 종류가 있다는 것을 알고 확신합니다. 스칼라는 그것은 당신이 설명하는 것보다 다소 덜 우아하게 인정되어야하며, 다른 과부하 처리합니다. 그 중 일부는 자바 상호 운용성, 그 중 일부는 타입 추론 알고리즘의 예리 경우를 치고 싶지 않다 때문입니다 때문에, 그리고 그 중 일부는 단순히 하스켈되지 않는 때문입니다.
글쎄, 그건 모두 아주 영리,하지만 난 당신이 이미 주요 질문에 대한 대답은 "아니오"의 다양한 종류가 있다는 것을 알고 확신합니다. 스칼라는 그것은 당신이 설명하는 것보다 다소 덜 우아하게 인정되어야하며, 다른 과부하 처리합니다. 그 중 일부는 자바 상호 운용성, 그 중 일부는 타입 추론 알고리즘의 예리 경우를 치고 싶지 않다 때문입니다 때문에, 그리고 그 중 일부는 단순히 하스켈되지 않는 때문입니다.
-
==============================
14.여기에 이미 큰 응답에 추가. 여기 마일 사빈 조합 유형 (조쉬의 생각)을 기반으로하지만, 또한 그들이 재귀 적으로 정의하게하는 요점은, 그래서 당신은 연합> 2 개 유형을 가질 수있다 (DEF [foo는 A : UNIL 또는 INT 또는 문자열 또는 목록 [문자열])
여기에 이미 큰 응답에 추가. 여기 마일 사빈 조합 유형 (조쉬의 생각)을 기반으로하지만, 또한 그들이 재귀 적으로 정의하게하는 요점은, 그래서 당신은 연합> 2 개 유형을 가질 수있다 (DEF [foo는 A : UNIL 또는 INT 또는 문자열 또는 목록 [문자열])
https://gist.github.com/aishfenton/2bb3bfa12e0321acfc904a71dda9bfbb
NB : 나는 프로젝트에 대한 위의 주위에 재생 후 그를 추가해야합니다, 나는 일반 오래된 합-타입 (서브 클래스로 즉 밀봉 특성)으로 되돌아가는 끝났다. 마일 사빈 조합 형식은 형식 매개 변수를 제한하는 중대하다,하지만 당신은 노동 조합 형식을 반환해야하는 경우 그것은 훨씬 제공하지 않습니다.
-
==============================
15.봉인의 추가와 문서, 보낸 사람 :
봉인의 추가와 문서, 보낸 사람 :
sealed class Expr case class Var (x: String) extends Expr case class Apply (f: Expr, e: Expr) extends Expr case class Lambda(x: String, e: Expr) extends Expr
밀봉 부에 대해서 :
from https://stackoverflow.com/questions/3508077/how-to-define-type-disjunction-union-types by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 스칼라에서 "바인딩 컨텍스트"는 무엇입니까? (0) | 2019.10.29 |
---|---|
[SCALA] <무엇을 할 : <, <% <및 = = 스칼라 2.8에 의미, 어디 그들은 문서화? (0) | 2019.10.29 |
[SCALA] 스칼라의 수율은 무엇입니까? (0) | 2019.10.29 |
[SCALA] 왜 예는 컴파일되지 않습니다 (공동, 콘트라 및 IN-) 분산 작업을 수행 일명 어떻게? (0) | 2019.10.29 |
[SCALA] 자기 유형과 특성 서브 클래스의 차이점은 무엇입니까? (0) | 2019.10.28 |