우리가 HList
, 우리는 먼저 필요로 Column
에 columnAttributes
을 나타내는 경우 HList
요소가 ColumnAttribute
의 부속 유형이되도록 구별해야합니다.
hlist constraintsLUBConstraint
및 IsDistinctConstraint
을 사용할 수 있습니다.
import shapeless.{Default => _, _}
import LUBConstraint._
import IsDistinctConstraint._
def acceptOnlyDistinctAttributes
[L <: HList : <<:[ColumnAttribute]#λ : IsDistinctConstraint](l: L): L = l
이제 우리는 불행하게도 우리는 이런 종류의 클래스에게 자신을 쓸 필요는 HList
는 그래서 모두 Encode
및 DistKey
을 포함 할 수 없습니다 제약 조건해야합니다.
=:=
을 사용하여 첫 번째 요소를 확인하고 NotContainsConstraint
을 확인하여 꼬리에 다른 유형이 포함되어 있지 않은지 확인할 수 있습니다. 우리는 지금 속성 ColumnAttributes
별개의 것을 컴파일 시간 보장이 아니라 모두 Encode
과 포함되지 않습니다
type CompressionEncoding = String
sealed trait ColumnAttribute
case class Default(value: String) extends ColumnAttribute
case class Identity(seed: Int, step: Int) extends ColumnAttribute
case class Encode(encoding: CompressionEncoding) extends ColumnAttribute
case object DistKey extends ColumnAttribute
import OnlyOneOfConstraint._
case class Column[
Attrs <: HList
: <<:[ColumnAttribute]#λ
: IsDistinctConstraint
: OnlyOneOf[Encode, DistKey.type]#λ
](columnAttributes: Attrs)
:
trait OnlyOneOfConstraint[L <: HList, A, B] extends Serializable
object OnlyOneOfConstraint {
def apply[L <: HList, A, B]
(implicit ooo: OnlyOneOfConstraint[L, A, B]): OnlyOneOfConstraint[L, A, B] = ooo
type OnlyOneOf[A, B] = {
type λ[L <: HList] = OnlyOneOfConstraint[L, A, B]
}
implicit def hnilOnlyOneOf[A, B] = new OnlyOneOfConstraint[HNil, A, B] {}
// head is A, so tail cannot contain B
implicit def hlistOnlyOneOfA[H, T <: HList, A, B](implicit
ncB: T NotContainsConstraint B,
eq: A =:= H,
oooT: OnlyOneOfConstraint[T, A, B]
) = new OnlyOneOfConstraint[H :: T, A, B] {}
// head is B, so tail cannot contain A
implicit def hlistOnlyOneOfB[H, T <: HList, A, B](implicit
ncA: T NotContainsConstraint A,
eq: B =:= H,
oooT: OnlyOneOfConstraint[T, A, B]
) = new OnlyOneOfConstraint[H :: T, A, B] {}
// head is not A or B
implicit def hlistOnlyOneOf[H, T <: HList, A, B](implicit
neqA: A =:!= H,
neqB: B =:!= H,
oooT: OnlyOneOfConstraint[T, A, B]
) = new OnlyOneOfConstraint[H :: T, A, B] {}
}
이제 우리는 (단순화)
Column
이러한 제약 조건을 사용하여 쓸 수 있습니다
DistKey
:
Column(DistKey :: Default("s") :: HNil)
// Column[shapeless.::[DistKey.type,shapeless.::[Default,shapeless.HNil]]] = Column(DistKey :: Default(s) :: HNil)
Column(Default("s") :: Encode("a") :: HNil)
// Column[shapeless.::[Default,shapeless.::[Encode,shapeless.HNil]]] = Column(Default(s) :: Encode(a) :: HNil)
Column(DistKey :: Default("s") :: Encode("a") :: HNil)
// <console>:93: error: could not find implicit value for evidence parameter of type OnlyOneOfConstraint[shapeless.::[DistKey.type,shapeless.::[Default,shapeless.::[Encode,shapeless.HNil]]],Encode,DistKey.type]
// Column(DistKey :: Default("s") :: Encode("a") :: HNil)
여기에 요점이 누락되었지만 Column? 시공에 대한 검증? –
그래, 나는 이미 그것에 대해 생각했다. 잘못된 값 (예 : 부정적인 '단계')을 구성하는 데 너무 많은 방법이 있으므로이 세트를 고려하지 않아도되므로 전반적으로 가치가 없습니다. 그러나 질문은 여전히 호기심을 위해서만 유효합니다. – chuwy
나는 당신이 시도하고있는 것이 확실하지 않지만, 당신이 끈임을 언급하고 예제를 제공하기 때문에 : 옵션의 HList는 실제로 ADT의 공정한 표현이 아닙니다. HLIST 제품은 다음과 같습니다. https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0#coproducts-and-discriminated-unions – pedrofurla