복붙노트

[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. ==============================

    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. ==============================

    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. ==============================

    3.: 당신은 당신이 원하는 정확히 무엇을 할 수 있도록, | (B 작성된 A) 도티, 새로운 실험 스칼라 컴파일러는, 노동 조합 유형을 지원합니다

    : 당신은 당신이 원하는 정확히 무엇을 할 수 있도록, | (B 작성된 A) 도티, 새로운 실험 스칼라 컴파일러는, 노동 조합 유형을 지원합니다

    def foo(xs: (String | Int)*) = xs foreach {
       case _: String => println("str")
       case _: Int => println("int")
    }
    
  4. ==============================

    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. ==============================

    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. ==============================

    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. ==============================

    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. ==============================

    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. ==============================

    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. ==============================

    10.당신은 OneOf라는 뭔가가 MetaScala, 한 번 봐 걸릴 수 있습니다. 나는이 일치 문 잘 작동하지 않습니다하지만 당신은 고차 함수를 사용하여 매칭을 시뮬레이션 할 수 있다는 인상을받을. 꽤 아직 작동하지 않습니다 아마도 때문에, 예를 들어, 가져온 부분을 살펴 보자하지만, "모의 일치"부분이 주석 있습니다.

    당신은 OneOf라는 뭔가가 MetaScala, 한 번 봐 걸릴 수 있습니다. 나는이 일치 문 잘 작동하지 않습니다하지만 당신은 고차 함수를 사용하여 매칭을 시뮬레이션 할 수 있다는 인상을받을. 꽤 아직 작동하지 않습니다 아마도 때문에, 예를 들어, 가져온 부분을 살펴 보자하지만, "모의 일치"부분이 주석 있습니다.

    이제 몇 가지 editorializing을 위해 : 나는 당신이 설명하는대로 등 Either3, Either4을, 정의에 대한 지독한 거기에 아무것도 생각하지 않습니다. 이 스칼라에 내장 된 표준 (22) 튜플 타입에 기본적으로 듀얼입니다. 그것은 확실히 스칼라 내장 한 경우 논리합 종류의 좋은, 그리고 것 아마도 {X, Y, Z} 같은 그들에 대한 몇 가지 좋은 구문.

  11. ==============================

    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. ==============================

    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. ==============================

    13.글쎄, 그건 모두 아주 영리,하지만 난 당신이 이미 주요 질문에 대한 대답은 "아니오"의 다양한 종류가 있다는 것을 알고 확신합니다. 스칼라는 그것은 당신이 설명하는 것보다 다소 덜 우아하게 인정되어야하며, 다른 과부하 처리합니다. 그 중 일부는 자바 상호 운용성, 그 중 일부는 타입 추론 알고리즘의 예리 경우를 치고 싶지 않다 때문입니다 때문에, 그리고 그 중 일부는 단순히 하스켈되지 않는 때문입니다.

    글쎄, 그건 모두 아주 영리,하지만 난 당신이 이미 주요 질문에 대한 대답은 "아니오"의 다양한 종류가 있다는 것을 알고 확신합니다. 스칼라는 그것은 당신이 설명하는 것보다 다소 덜 우아하게 인정되어야하며, 다른 과부하 처리합니다. 그 중 일부는 자바 상호 운용성, 그 중 일부는 타입 추론 알고리즘의 예리 경우를 치고 싶지 않다 때문입니다 때문에, 그리고 그 중 일부는 단순히 하스켈되지 않는 때문입니다.

  14. ==============================

    14.여기에 이미 큰 응답에 추가. 여기 마일 사빈 조합 유형 (조쉬의 생각)을 기반으로하지만, 또한 그들이 재귀 적으로 정의하게하는 요점은, 그래서 당신은 연합> 2 개 유형을 가질 수있다 (DEF [foo는 A : UNIL 또는 INT 또는 문자열 또는 목록 [문자열])

    여기에 이미 큰 응답에 추가. 여기 마일 사빈 조합 유형 (조쉬의 생각)을 기반으로하지만, 또한 그들이 재귀 적으로 정의하게하는 요점은, 그래서 당신은 연합> 2 개 유형을 가질 수있다 (DEF [foo는 A : UNIL 또는 INT 또는 문자열 또는 목록 [문자열])

    https://gist.github.com/aishfenton/2bb3bfa12e0321acfc904a71dda9bfbb

    NB : 나는 프로젝트에 대한 위의 주위에 재생 후 그를 추가해야합니다, 나는 일반 오래된 합-타입 (서브 클래스로 즉 밀봉 특성)으로 되돌아가는 끝났다. 마일 사빈 조합 형식은 형식 매개 변수를 제한하는 중대하다,하지만 당신은 노동 조합 형식을 반환해야하는 경우 그것은 훨씬 제공하지 않습니다.

  15. ==============================

    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
    

    밀봉 부에 대해서 :

  16. from https://stackoverflow.com/questions/3508077/how-to-define-type-disjunction-union-types by cc-by-sa and MIT license