我想引入一个具有比较编号的类型类,例如类型,但还要有日期。
这是我的类型类别:
trait NumberLike[A] {
def lessThenOrEqual[B](a: A, b: B): Boolean
def moreThenOrEqual[B](a: A, b: B): Boolean
}
object NumberLike {
def apply[A](implicit numericalLike: NumberLike[A]): NumberLike[A] =
numericalLike
def lessThenOrEqual[A: NumberLike, B](a: A)(b: B): Boolean =
NumberLike[A].lessThenOrEqual(a, b)
def moreThenOrEqual[A: NumberLike, B](a: A)(b: B): Boolean =
NumberLike[A].moreThenOrEqual(a, b)
def instance[A, B](
lTOE: (A, B) => Boolean,
mTOE: (A, B) => Boolean
): NumberLike[A] = new NumberLike[A] {
def lessThenOrEqual[B](a: A, b: B): Boolean = lTOE(a, b)
def moreThenOrEqual[B](a: A, b: B): Boolean = mTOE(a, b)
}
implicit class NumericalLikeOps[A: NumberLike](a: A) {
def lessThenOrEqual[B](b: B): Boolean = NumberLike[A].lessThenOrEqual(a, b)
def moreThenOrEqual[B](b: B): Boolean = NumberLike[A].moreThenOrEqual(a, b)
}
}
问题是我想让函数lessThenOrEqual(a,b)可以放入另一种类型,因为我将比较整数和浮点数。但是,如果我可以比较的话,每种类型的类型类将只是一个,例如,如果一个类型具有多个其他类型的整数,可以说整数和浮点数。因此,类型B仅是功能说明,而不应该是类型类的变量。
对于实例,我将遇到类型B不被接受为函数变量的问题。
是否有任何解决方法?或者换句话说,如何在实例定义中使变量B只是针对lTOE的特定功能?
编辑:
我使用了解决方案提出的以下解决方案:
trait NumberLike[A] {
type B
def lessThenOrEqual(a: A, b: B): Boolean
def moreThenOrEqual(a: A, b: B): Boolean
}
object NumberLike {
type Aux[A, B0] = NumberLike[A] { type B = B0 }
def apply[A, B](implicit numberLike: Aux[A, B]): Aux[A, B] =
numberLike
def lessThenOrEqual[A, B](a: A)(b: B)(
implicit numberLike: Aux[A, B]): Boolean =
numberLike.lessThenOrEqual(a, b)
def moreThenOrEqual[A, B](a: A)(b: B)(
implicit numberLike: Aux[A, B]): Boolean =
numberLike.moreThenOrEqual(a, b)
def instance[A, B0](
lTOE: (A, B0) => Boolean,
mTOE: (A, B0) => Boolean
): Aux[A, B0] = new NumberLike[A] {
type B = B0
def lessThenOrEqual(a: A, b: B): Boolean = lTOE(a, b)
def moreThenOrEqual(a: A, b: B): Boolean = mTOE(a, b)
}
object ops {
implicit class NumberLikeOps[A](a: A) {
def lessThenOrEqual[B](b: B)(implicit numberLike: Aux[A, B]): Boolean =
numberLike.lessThenOrEqual(a, b)
def moreThenOrEqual[B](b: B)(implicit numberLike: Aux[A, B]): Boolean =
numberLike.moreThenOrEqual(a, b)
}
}
implicit val intIntNumberLike: Aux[Int, Int] = instance(_ <= _, _ >= _)
implicit val intFloatNumberLike: Aux[Int, Float] = instance(_ <= _, _ >= _)
implicit val DoubleDoubleNumberLike: Aux[Double, Double] = instance(_ <= _, _ >= _)
implicit val floatFloatNumberLike: Aux[Float, Float] = instance(_ <= _, _ >= _)
}
现在我正在尝试获取Hlist的实例
type NumberLikeType = Int :+: Double :+: Float :+: CNil
我想定义的是通过使用无形的函数lessThenOrEqual和moreThenOrEqual,但是我没有得到解决方案。这是我尝试过的:
implicit val cnilNumericalLike: NumberLike[CNil] =
new NumberLike[CNil] {
override def lessThenOrEqual(a: CNil, b: B): Boolean = true
override def moreThenOrEqual(a: CNil, b: B): Boolean = true
}
implicit def coproductConsTransform[L, R, LL, RR <: Coproduct](
implicit
lch: NumberLike[L],
lch2: NumberLike[LL],
rch: NumberLike[R],
rch2: NumberLike[RR]): NumberLike[L :+: R] =
new NumberLike[L :+: R] {
override def lessThenOrEqual(t: L :+: R, b: LL :+: RR): Boolean = {
t match {
case Inl(l) =>
b match {
case Inl(ll) => lch.lessThenOrEqual(l, ll)
case Inr(rr) => lch.lessThenOrEqual(l, rr)
}
case Inr(r) => rch.lessThenOrEqual(r, b)
}
}
override def moreThenOrEqual(t: L :+: R, b: L :+: R): Boolean = {
t match {
case Inl(l) =>
b match {
case Inl(bl) => lch.moreThenOrEqual(l, bl)
case Inr(br) => false
}
case Inr(r) =>
b match {
case Inl(bl) => false
case Inr(br) => rch.moreThenOrEqual(r, br)
}
}
}
}
implicit def genericTransform[A, B](implicit
gen: Generic.Aux[A, B],
cch: Lazy[NumberLike[B]]): NumberLike[A] =
new NumberLike[A] {
def lessThenOrEqual(a: A, b: A): Boolean =
cch.value.lessThenOrEqual(gen.to(a), gen.to(b))
def moreThenOrEqual(a: A, b: A): Boolean =
cch.value.moreThenOrEqual(gen.to(a), gen.to(b))
}
我知道输入类型是错误的,但是不知道要介绍什么。
听起来像您具有多参数类型类。
trait NumberLike[A, B] {
def lessThenOrEqual(a: A, b: B): Boolean
def moreThenOrEqual(a: A, b: B): Boolean
}
object NumberLike {
def apply[A, B](implicit numberLike: NumberLike[A, B]): NumberLike[A, B] =
numberLike
def lessThenOrEqual[A, B](a: A)(b: B)(implicit numberLike: NumberLike[A, B]): Boolean =
numberLike.lessThenOrEqual(a, b)
def moreThenOrEqual[A, B](a: A)(b: B)(implicit numberLike: NumberLike[A, B]): Boolean =
numberLike.moreThenOrEqual(a, b)
def instance[A, B](
lTOE: (A, B) => Boolean,
mTOE: (A, B) => Boolean
): NumberLike[A, B] = new NumberLike[A, B] {
def lessThenOrEqual(a: A, b: B): Boolean = lTOE(a, b)
def moreThenOrEqual(a: A, b: B): Boolean = mTOE(a, b)
}
object ops {
implicit class NumberLikeOps[A, B](a: A) {
def lessThenOrEqual(b: B)(implicit numberLike: NumberLike[A, B]): Boolean = numberLike.lessThenOrEqual(a, b)
def moreThenOrEqual(b: B)(implicit numberLike: NumberLike[A, B]): Boolean = numberLike.moreThenOrEqual(a, b)
}
}
implicit val intIntNumberLike: NumberLike[Int, Int] = instance(_ <= _, _ >= _)
implicit val intFloatNumberLike: NumberLike[Int, Float] = instance(_ <= _, _ >= _)
}
import NumberLike.ops._
1 lessThenOrEqual 2
1 lessThenOrEqual 2.0f
也可以按照@LuisMiguelMejíaSuárez的建议移动B
来键入成员
trait NumberLike[A] {
type B
def lessThenOrEqual(a: A, b: B): Boolean
def moreThenOrEqual(a: A, b: B): Boolean
}
object NumberLike {
type Aux[A, B0] = NumberLike[A] { type B = B0 }
def apply[A, B](implicit numberLike: Aux[A, B]): Aux[A, B] =
numberLike
def lessThenOrEqual[A, B](a: A)(b: B)(implicit numberLike: Aux[A, B]): Boolean =
numberLike.lessThenOrEqual(a, b)
def moreThenOrEqual[A, B](a: A)(b: B)(implicit numberLike: Aux[A, B]): Boolean =
numberLike.moreThenOrEqual(a, b)
def instance[A, B0](
lTOE: (A, B0) => Boolean,
mTOE: (A, B0) => Boolean
): Aux[A, B0] = new NumberLike[A] {
type B = B0
def lessThenOrEqual(a: A, b: B): Boolean = lTOE(a, b)
def moreThenOrEqual(a: A, b: B): Boolean = mTOE(a, b)
}
object ops {
implicit class NumberLikeOps[A](a: A) {
def lessThenOrEqual[B](b: B)(implicit numberLike: Aux[A, B]): Boolean = numberLike.lessThenOrEqual(a, b)
def moreThenOrEqual[B](b: B)(implicit numberLike: Aux[A, B]): Boolean = numberLike.moreThenOrEqual(a, b)
}
}
implicit val intIntNumberLike: Aux[Int, Int] = instance(_ <= _, _ >= _)
implicit val intFloatNumberLike: Aux[Int, Float] = instance(_ <= _, _ >= _)
}
import NumberLike.ops._
1 lessThenOrEqual 2
1 lessThenOrEqual 2.0f
如果将B
保留在方法级别,则不能使用构造函数方法instance
(Scala 2中没有多态函数,Scala 3中只有will appear)。您应该通过new
创建实例。同样不清楚如何定义实例,例如如何比较Int
与任意B
。
trait NumberLike[A] {
def lessThenOrEqual[B](a: A, b: B): Boolean
def moreThenOrEqual[B](a: A, b: B): Boolean
}
object NumberLike {
def apply[A](implicit numberLike: NumberLike[A]): NumberLike[A] =
numberLike
def lessThenOrEqual[A: NumberLike, B](a: A)(b: B): Boolean =
NumberLike[A].lessThenOrEqual(a, b)
def moreThenOrEqual[A: NumberLike, B](a: A)(b: B): Boolean =
NumberLike[A].moreThenOrEqual(a, b)
object ops {
implicit class NumberLikeOps[A: NumberLike](a: A) {
def lessThenOrEqual[B](b: B): Boolean = NumberLike[A].lessThenOrEqual(a, b)
def moreThenOrEqual[B](b: B): Boolean = NumberLike[A].moreThenOrEqual(a, b)
}
}
implicit val intNumberLike: NumberLike[Int] = new NumberLike[Int] {
override def lessThenOrEqual[B](a: Int, b: B): Boolean = ???
override def moreThenOrEqual[B](a: Int, b: B): Boolean = ???
}
}