具有多个参数的类型类。如何召唤只有一个参数的实例?
Typeclass with multiple parameters. How to summon an instance having only one parameter?
我一直在尝试创建某种类型类,但遇到了隐式解析问题。
基本上我想生成随机数据并调整生成参数 - 数字间隔,数组长度和间隔等。
这是我现在得到的:
import scala.util.Random
trait PrimitiveGenerator[T <: AnyVal, Bounds] {
def generate(bounds: Bounds): T
def generatePossibly(bounds: Bounds): Option[T] = if (Random.nextDouble() < 0.5) None else Some(generate(bounds))
}
object PrimitiveGenerator {
def apply[A <: AnyVal](implicit impl: PrimitiveGenerator[A, _]) = impl
}
object Generators {
implicit object IntGenerator extends PrimitiveGenerator[Int, (Int, Int)] {
override def generate(bounds: (Int, Int) = (0, 1)): Int = Random.nextInt((bounds._2 - bounds._1) + 1) + bounds._1
}
}
object Test extends App {
import Generators._
PrimitiveGenerator[Int].generate((0, 1)) //error is here
}
在 Intellij Idea 中,这是失败的:
found : (Int, Int)
required: _ where type _
PrimitiveGenerator[Int].generate((0, 1))
我知道这里使用下划线是错误的,但我如何重写它以仅基于第一个类型参数 (A) 来调用 DataGenerator 的实例。从编译的角度来看,它似乎非常安全:
如果编译器找到 Int 的 DataGenerator,仅在一个示例中,它会立即使用它,如果它发现其中几个具有不同的 Bounds,则只是 returns 一个错误。我可能会解决这个错误,将这个参数添加到隐式解析中。那你怎么看?
编辑 1
感谢@Dmytro Mitin 解决了这个问题!
进一步看,我想为 Array 做一个实现,这样如果我们想为数组调用一个实例,我们应该有一个 Array 的参数类型的实例,就像这样:
import scala.reflect.ClassTag
import scala.util.Random
trait PrimitiveGenerator[T] {
type Bounds
def generate(bounds: Bounds): T
def generatePossibly(bounds: Bounds): Option[T] = if (Random.nextDouble() < 0.5) None else Some(generate(bounds))
}
object PrimitiveGenerator {
type Aux[T, Bounds0] = PrimitiveGenerator[T] { type Bounds = Bounds0 }
def apply[A](implicit impl: PrimitiveGenerator[A]): Aux[A, impl.Bounds] = impl
}
object Generators {
implicit object IntGenerator extends PrimitiveGenerator[Int] {
override type Bounds = (Int, Int)
override def generate(bounds: (Int, Int) = (0, 1)): Int = Random.nextInt((bounds._2 - bounds._1) + 1) + bounds._1
}
implicit def toGenericArrayGenerator[A](implicit generator: PrimitiveGenerator[A],
classTag: ClassTag[A]): PrimitiveGenerator[Array[A]] = new PrimitiveGenerator[Array[A]] {
override type Bounds = ((Int, Int), generator.Bounds) //It means generate array of length from n to m where elements comply to Bounds of base generator
override def generate(bounds: Bounds): Array[A] = {
Array[A]()
}
}
}
object Test extends App {
import Generators._
println(PrimitiveGenerator[Int].generate((0, 42)))
PrimitiveGenerator[Array[Int]].generate((1 -> 10, 0 -> 42))
}
现在我正在尝试动态创建数组生成器,并且边界根据基本生成器边界(按计划)略有变化。
但是出了点问题,现在我有:
Error: type mismatch;
found : ((Int, Int), (Int, Int))
required: impl.Bounds
PrimitiveGenerator[Array[Int]].generate((1 -> 10, 0 -> 42))
如何解决?
例如尝试
object PrimitiveGenerator {
def apply[A <: AnyVal] = new PartiallyApplied[A]
class PartiallyApplied[A <: AnyVal] {
def apply[B]()(implicit impl: PrimitiveGenerator[A, B]) = impl
}
}
object Test extends App {
import Generators._
PrimitiveGenerator[Int]().generate((0, 1))
}
或
object PrimitiveGenerator {
def generate[A <: AnyVal, B](b: B)(implicit impl: PrimitiveGenerator[A, B]) = impl.generate(b)
}
object Test extends App {
import Generators._
PrimitiveGenerator.generate((0, 1))
}
或
trait PrimitiveGenerator[T <: AnyVal] {
type Bounds
def generate(bounds: Bounds): T
def generatePossibly(bounds: Bounds): Option[T] = if (Random.nextDouble() < 0.5) None else Some(generate(bounds))
}
object PrimitiveGenerator {
type Aux[T <: AnyVal, Bounds0] = PrimitiveGenerator[T] { type Bounds = Bounds0 }
def apply[A <: AnyVal](implicit impl: PrimitiveGenerator[A]): Aux[A, impl.Bounds] = impl
}
object Generators {
implicit object IntGenerator extends PrimitiveGenerator[Int] {
override type Bounds = (Int, Int)
override def generate(bounds: (Int, Int) = (0, 1)): Int = Random.nextInt((bounds._2 - bounds._1) + 1) + bounds._1
}
}
object Test extends App {
import Generators._
PrimitiveGenerator[Int].generate((0, 1))
}
或
trait PrimitiveGenerator[T <: AnyVal] {
type Bounds = (T, T)
def generate(bounds: Bounds): T
def generatePossibly(bounds: Bounds): Option[T] = if (Random.nextDouble() < 0.5) None else Some(generate(bounds))
}
object PrimitiveGenerator {
def apply[A <: AnyVal](implicit impl: PrimitiveGenerator[A]): PrimitiveGenerator[A] = impl
}
object Generators {
implicit object IntGenerator extends PrimitiveGenerator[Int] {
override def generate(bounds: (Int, Int) = (0, 1)): Int = Random.nextInt((bounds._2 - bounds._1) + 1) + bounds._1
}
}
object Test extends App {
import Generators._
PrimitiveGenerator[Int].generate((0, 1))
}
我一直在尝试创建某种类型类,但遇到了隐式解析问题。 基本上我想生成随机数据并调整生成参数 - 数字间隔,数组长度和间隔等。 这是我现在得到的:
import scala.util.Random
trait PrimitiveGenerator[T <: AnyVal, Bounds] {
def generate(bounds: Bounds): T
def generatePossibly(bounds: Bounds): Option[T] = if (Random.nextDouble() < 0.5) None else Some(generate(bounds))
}
object PrimitiveGenerator {
def apply[A <: AnyVal](implicit impl: PrimitiveGenerator[A, _]) = impl
}
object Generators {
implicit object IntGenerator extends PrimitiveGenerator[Int, (Int, Int)] {
override def generate(bounds: (Int, Int) = (0, 1)): Int = Random.nextInt((bounds._2 - bounds._1) + 1) + bounds._1
}
}
object Test extends App {
import Generators._
PrimitiveGenerator[Int].generate((0, 1)) //error is here
}
在 Intellij Idea 中,这是失败的:
found : (Int, Int)
required: _ where type _
PrimitiveGenerator[Int].generate((0, 1))
我知道这里使用下划线是错误的,但我如何重写它以仅基于第一个类型参数 (A) 来调用 DataGenerator 的实例。从编译的角度来看,它似乎非常安全: 如果编译器找到 Int 的 DataGenerator,仅在一个示例中,它会立即使用它,如果它发现其中几个具有不同的 Bounds,则只是 returns 一个错误。我可能会解决这个错误,将这个参数添加到隐式解析中。那你怎么看?
编辑 1 感谢@Dmytro Mitin 解决了这个问题! 进一步看,我想为 Array 做一个实现,这样如果我们想为数组调用一个实例,我们应该有一个 Array 的参数类型的实例,就像这样:
import scala.reflect.ClassTag
import scala.util.Random
trait PrimitiveGenerator[T] {
type Bounds
def generate(bounds: Bounds): T
def generatePossibly(bounds: Bounds): Option[T] = if (Random.nextDouble() < 0.5) None else Some(generate(bounds))
}
object PrimitiveGenerator {
type Aux[T, Bounds0] = PrimitiveGenerator[T] { type Bounds = Bounds0 }
def apply[A](implicit impl: PrimitiveGenerator[A]): Aux[A, impl.Bounds] = impl
}
object Generators {
implicit object IntGenerator extends PrimitiveGenerator[Int] {
override type Bounds = (Int, Int)
override def generate(bounds: (Int, Int) = (0, 1)): Int = Random.nextInt((bounds._2 - bounds._1) + 1) + bounds._1
}
implicit def toGenericArrayGenerator[A](implicit generator: PrimitiveGenerator[A],
classTag: ClassTag[A]): PrimitiveGenerator[Array[A]] = new PrimitiveGenerator[Array[A]] {
override type Bounds = ((Int, Int), generator.Bounds) //It means generate array of length from n to m where elements comply to Bounds of base generator
override def generate(bounds: Bounds): Array[A] = {
Array[A]()
}
}
}
object Test extends App {
import Generators._
println(PrimitiveGenerator[Int].generate((0, 42)))
PrimitiveGenerator[Array[Int]].generate((1 -> 10, 0 -> 42))
}
现在我正在尝试动态创建数组生成器,并且边界根据基本生成器边界(按计划)略有变化。 但是出了点问题,现在我有:
Error: type mismatch;
found : ((Int, Int), (Int, Int))
required: impl.Bounds
PrimitiveGenerator[Array[Int]].generate((1 -> 10, 0 -> 42))
如何解决?
例如尝试
object PrimitiveGenerator {
def apply[A <: AnyVal] = new PartiallyApplied[A]
class PartiallyApplied[A <: AnyVal] {
def apply[B]()(implicit impl: PrimitiveGenerator[A, B]) = impl
}
}
object Test extends App {
import Generators._
PrimitiveGenerator[Int]().generate((0, 1))
}
或
object PrimitiveGenerator {
def generate[A <: AnyVal, B](b: B)(implicit impl: PrimitiveGenerator[A, B]) = impl.generate(b)
}
object Test extends App {
import Generators._
PrimitiveGenerator.generate((0, 1))
}
或
trait PrimitiveGenerator[T <: AnyVal] {
type Bounds
def generate(bounds: Bounds): T
def generatePossibly(bounds: Bounds): Option[T] = if (Random.nextDouble() < 0.5) None else Some(generate(bounds))
}
object PrimitiveGenerator {
type Aux[T <: AnyVal, Bounds0] = PrimitiveGenerator[T] { type Bounds = Bounds0 }
def apply[A <: AnyVal](implicit impl: PrimitiveGenerator[A]): Aux[A, impl.Bounds] = impl
}
object Generators {
implicit object IntGenerator extends PrimitiveGenerator[Int] {
override type Bounds = (Int, Int)
override def generate(bounds: (Int, Int) = (0, 1)): Int = Random.nextInt((bounds._2 - bounds._1) + 1) + bounds._1
}
}
object Test extends App {
import Generators._
PrimitiveGenerator[Int].generate((0, 1))
}
或
trait PrimitiveGenerator[T <: AnyVal] {
type Bounds = (T, T)
def generate(bounds: Bounds): T
def generatePossibly(bounds: Bounds): Option[T] = if (Random.nextDouble() < 0.5) None else Some(generate(bounds))
}
object PrimitiveGenerator {
def apply[A <: AnyVal](implicit impl: PrimitiveGenerator[A]): PrimitiveGenerator[A] = impl
}
object Generators {
implicit object IntGenerator extends PrimitiveGenerator[Int] {
override def generate(bounds: (Int, Int) = (0, 1)): Int = Random.nextInt((bounds._2 - bounds._1) + 1) + bounds._1
}
}
object Test extends App {
import Generators._
PrimitiveGenerator[Int].generate((0, 1))
}