TL;博士 :我怎样做类似下面的由代码:
def notFunctor[M[_] : Not[Functor]](m: M[_]) = s"$m is not a functor"
在“ Not[Functor]
”,正在这里组成部分。
我希望它成功时所提供的“M”是不是一个函子,否则失败的编译器。
解决 :跳过这个问题的其余部分,正前方去下面的答案。
我试图做到的是,粗略地说,“反面证据”。
伪代码会看起来像这样:
// type class for obtaining serialization size in bytes.
trait SizeOf[A] { def sizeOf(a: A): Long }
// type class specialized for types whose size may vary between instances
trait VarSizeOf[A] extends SizeOf[A]
// type class specialized for types whose elements share the same size (e.g. Int)
trait FixedSizeOf[A] extends SizeOf[A] {
def fixedSize: Long
def sizeOf(a: A) = fixedSize
}
// SizeOf for container with fixed-sized elements and Length (using scalaz.Length)
implicit def fixedSizeOf[T[_] : Length, A : FixedSizeOf] = new VarSizeOf[T[A]] {
def sizeOf(as: T[A]) = ... // length(as) * sizeOf[A]
}
// SizeOf for container with scalaz.Foldable, and elements with VarSizeOf
implicit def foldSizeOf[T[_] : Foldable, A : SizeOf] = new VarSizeOf[T[A]] {
def sizeOf(as: T[A]) = ... // foldMap(a => sizeOf(a))
}
请记住, fixedSizeOf()
是优选的,其中重要,因为它为我们节省了集合的遍历。
这样一来,对于只有容器类型Length
被定义(但不Foldable
),以及对于在其中一个元素FixedSizeOf
定义,我们可以得到更好的性能。
对于其余情形下,我们去了收集和总结各个大小。
我的问题是在两种情况下Length
和Foldable
被用于容器限定,并且FixedSizeOf
针对元件限定。 这是在这里一个非常普遍的情况下(例如,: List[Int]
已两者定义)。
例:
scala> implicitly[SizeOf[List[Int]]].sizeOf(List(1,2,3))
<console>:24: error: ambiguous implicit values:
both method foldSizeOf of type [T[_], A](implicit evidence$1: scalaz.Foldable[T], implicit evidence$2: SizeOf[A])VarSizeOf[T[A]]
and method fixedSizeOf of type [T[_], A](implicit evidence$1: scalaz.Length[T], implicit evidence$2: FixedSizeOf[A])VarSizeOf[T[A]]
match expected type SizeOf[List[Int]]
implicitly[SizeOf[List[Int]]].sizeOf(List(1,2,3))
我想是能够依靠Foldable
型类仅在Length
+ FixedSizeOf
组合不适用。
为此,我可以改变的定义foldSizeOf()
接受VarSizeOf
元素:
implicit def foldSizeOfVar[T[_] : Foldable, A : VarSizeOf] = // ...
现在,我们必须填写覆盖问题部分Foldable
与容器FixedSizeOf
元素, 没有Length
定义 。 我不知道如何处理这一点,但伪代码看起来是这样的:
implicit def foldSizeOfFixed[T[_] : Foldable : Not[Length], A : FixedSizeOf] = // ...
在“ Not[Length]
”,很明显,正在这里组成部分。
部分解决方案我知道
1)定义的低优先级implicits一个类和扩展它,如在“看到的object Predef extends LowPriorityImplicits
”。 最后隐式的( foldSizeOfFixed()
可在父类中定义,并且将通过从子类替代被覆盖。
我不是在这个选项感兴趣,因为我希望最终能够支持递归使用SizeOf
,这将防止在低优先级的基类隐含从依靠那些在子类(在这里我的理解是否正确?编辑:!错隐查找从子类的情况下工作,这是一个可行的解决方案)!
2)更粗糙的方法是依赖于Option[TypeClass]
(例如,: Option[Length[List]]
少数那些和I可以只写一个大醇”隐式,其拾取Foldable
和SizeOf
为强制性的和Length
和FixedSizeOf
作为。可选的,并依赖于后者(如果可用)(来源: 点击这里 )
这里的两个问题是缺乏模块化和回落至运行时异常时没有相关类型的类的实例可以定位(这个例子或许可以进行此解决方案的工作,但是这并不总是可能的)
编辑:这是我能得到可选implicits最好的。 这还没有实现:
implicit def optionalTypeClass[TC](implicit tc: TC = null) = Option(tc)
type OptionalLength[T[_]] = Option[Length[T]]
type OptionalFixedSizeOf[T[_]] = Option[FixedSizeOf[T]]
implicit def sizeOfContainer[
T[_] : Foldable : OptionalLength,
A : SizeOf : OptionalFixedSizeOf]: SizeOf[T[A]] = new SizeOf[T[A]] {
def sizeOf(as: T[A]) = {
// optionally calculate using Length + FixedSizeOf is possible
val fixedLength = for {
lengthOf <- implicitly[OptionalLength[T]]
sizeOf <- implicitly[OptionalFixedSizeOf[A]]
} yield lengthOf.length(as) * sizeOf.fixedSize
// otherwise fall back to Foldable
fixedLength.getOrElse {
val foldable = implicitly[Foldable[T]]
val sizeOf = implicitly[SizeOf[A]]
foldable.foldMap(as)(a => sizeOf.sizeOf(a))
}
}
}
除了这与碰撞fixedSizeOf()
从早期的,这仍然是必要的。
感谢您的帮助或透视:-)