Nat列表在0到2之间的类?

时间:2016-08-27 17:32:25

标签: scala shapeless

使用Peter Neyens的帮助answer,我尝试创建一个只包含X小于或等于2的Nat类。

import shapeless._
import shapeless.ops.nat._
import shapeless.nat._

case class X[A <: Nat](values: List[A])(implicit ev: LTEq[A, _2])

以下作品:

scala> X( List(_1, _1, _1) )
res6: X[shapeless.nat._1] = X(List(Succ(), Succ(), Succ()))

但是当我使用不同的Nat时,即_1_2时,我遇到了编译时错误:

scala> X( List(_1, _2) )
<console>:23: error: could not find implicit value for parameter ev: 
   shapeless.ops.nat.LTEq[shapeless.Succ[_ >: shapeless.Succ[shapeless._0] 
       with shapeless._0 <: Serializable with shapeless.Nat],shapeless.nat._2]
       X( List(_1, _2) )
        ^

然后我尝试了:

scala> case class X(values: List[_ <: Nat])
defined class X

适用于sub-classes的{​​{1}},但不受Nat限制:

<= 2

如何撰写上面scala> X(List(_1, _2, _3)) res8: X = X(List(Succ(), Succ(), Succ())) 的{​​{1}}列表,其中X列在Nat范围内?

我的想法是使用0 to 2MyZeroMyOne的代数数据类型,但不确定这是最干净的方法。

最后,在我看来,MyTwo要求拥有类型参数是不必要的。可以推断出也可以在我想要的X

的实现中遗漏它

1 个答案:

答案 0 :(得分:1)

为手动绑定引入新的ADT可能是唯一的方法,因为您需要使用只能通过常量实现的不同宏实现对象进行绑定。

明显的通用解决方案是为可能的比较器操作生成类型证据的隐式机制,例如当使用<<=Nat时可能产生任何隐含证据这只会比较Nat的基础int值。

您仍然可以使用NatOps使用原生toInt手动执行此操作。

您点击另一个约束,查看Nat的实施,即需要Literal(Constant())

val n = i.tree match {
  case Literal(Constant(n: Int)) => n
  case _ =>
    c.abort(c.enclosingPosition, s"Expression ${i.tree} does not evaluate to an Int constant")
}

所以这可能会给你留下如下内容:

abstract class SizeBound[N <: Nat](n: N)

import shapeless.nat._

implicit object ZeroBound extends SizeBound(_0)
implicit object OneBound extends SizeBound(_1)
implicit object TwoBound extends SizeBound(_2)

然后是显而易见的def op[T <: Nat : SizeBound](...)。也许周围的一个无形大师有一个更好的方法,我很遗憾只是一个新手。

<强>更新

我刚才有一个闪回思考这个问题,并记住Miles如何做出Shapeless Fizz的嗡嗡声,即它如何依靠Mod.Aux在nat之间进行mod划分。

长话短说,已经有了一个类型类:

import shapeless.ops.nat._
import shapeless.nat._

def doStuff[N <: Nat](n: N)(
  // There is a _2 type already available.
  implicit ev: LT[N, _2]
) = { // now you know N is less than _2}

LT显然低于,并且您可以获得更多变体。 Here you go,您也可以在这里浏览其他有趣的内容。这是有效的,但不是在您使用_2.type时,而是必须直接使用_2

中的import shapeless.nat._类型