递归Poly1来递归类型参数

时间:2015-07-17 13:01:28

标签: scala recursion shapeless

我使用无形的Poly1来构建案例类的方案(描述它们的序列化)。构建Schema

case class A(b: B, c: String, d: List[Int], e: Option[List[Option[Int]]])

每个包含的类型都需要一个模式。

Schema对象(除了其他内容)保存其成员的示例值。我从实例中为所有原语类型(IntFloatString,...)提取这些示例值,其方案由动态构建我的Poly1。所有复杂类型(我的意思是指具有其他成员值的自定义类型)都会被引用,因为它们也可能具有自定义序列化方法。通过要求在隐式范围中存在模式,可以很容易地解决这个问题。

现在知道如何为任何列表(或任何其他集合)构建Schema iff 类型参数有Schema。对于像Option这样的其他monad类型也是如此。

Poly1的想法是将成员类型映射到他们的方案,这些方案可以动态构建,也可以从隐式范围中查找。这需要我为所有原始类型以及所有必需的monad定义一个案例。这种方法通常有效,但有很多样板。

当前Poly1对象(NGSchematrait所有Schema[T]个实例都会继承,ref[T]会从Schema[T]查找integer个实例隐式范围和函数longfloatSchema[T]使用给定示例构造private object typeRecursion extends Poly1 { implicit val caseInt = at[Int] [NGSchema](integer(_)) implicit val caseLong = at[Long] [NGSchema](long(_)) implicit val caseFloat = at[Float] [NGSchema](float(_)) ... implicit def caseOption[T: Schema](implicit c: Case.Aux[T, NGSchema]) = at[Option[T]][NGSchema]{ case Some(v) => OptionSchema(typeRecursion(v)(c)) case None => OptionSchema(ref[T]) } implicit def caseList[T: Schema](implicit c: Case.Aux[T, NGSchema]) = at[List[T]][NGSchema]{ case v :: tl => SeqSchema(typeRecursion(v)(c)) case Nil => SeqSchema(ref[T]) } ... implicit def caseElse[T: Schema] = at[T][NGSchema]{ case _ => ref[T] } }

e

但是在成员Option[List[Option[Int]]]的情况下,这会失败,因为Poly1的模式将不会出现在隐式作用域中,因为它应该在运行中构建。我相信我的Option应该是递归的,以便很好地解决这个问题。然而,这会产生这样的问题:Option[List[Option[Int]]]情况确实需要某种类型绑定用于内部最多类型,这在递归中的那个点是未知的 iff 这是一个复杂类型,因为这个不能在飞行中构建。

我希望功能会将OptionSchema(SeqSchema(OptionSchema(integer(example))映射到Option[B],而Schema[B]应该从隐式范围查找OptionSchema(ref[B])并执行// for example: language = @"en" and region = @"UK" NSString* languageDescription = [NSString stringWithFormat:@"%@-%@",language,region] [NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects: languageDescription, nil] forKey: @"AppleLanguages"]; [[NSUserDefaults standardUserDefaults] synchronize]; //to make the change immediate

这是解决问题的正确方法吗?

1 个答案:

答案 0 :(得分:1)

Poly1本身不是implicit,只有案例是隐含的。我认为你混淆了类型类级别和价值级别。我会将隐式Schema实例的提供与实际操作它们的函数(可能只是普通函数?)分开:

implicit object IntSchema extends NGSchema[Int]{ ... }
implicit def optionSchema[T: Schema] = new Schema[Option[T]]{...}
...
def myFunction[T: Schema](t: T) = ... //or Poly with cases here if you need it.