一个案例类的字符串字段的调整值

问题描述 投票:5回答:1

我写使用shapeless,需要一个case class的实例,并修剪是字符串字段的所有值的通用函数。此案类可以有可选字段,嵌套的对象,列表等。

我有一个案例类Person

case class Person(name: Option[String], address: List[String], friends: List[Person])

我目前拥有的功能:

import shapeless._, ops.hlist._

  object trimmer extends Poly1 {
    implicit val stringOptCase = at[Option[String]](_.map(_.trim))
    implicit val stringListCase = at[List[String]](_.map(_.trim))
    implicit def skipCase[A] = at[A](identity)
  }

  def trimStringValues[A, R <: HList](a: A)(implicit
                                     gen: Generic.Aux[A, R],
                                     mapper: Mapper.Aux[trimmer.type, R, R]
  ) = gen.from(mapper(gen.to(a)))

当我使用上述功能,它仅适用于类name的根级别Person场。它不会对列表或对象领域的工作。

val person = Person(name = Some(" john "), address = List(" ny"," vegas "), friends = List(Person(Some(" alicia"), List(" peter"), Nil)))

trimStringValues(person) // Person(Some(john),List(ny, vegas),List(Person(Some( alicia),List( peter),List())))

我该如何解决这个问题?

scala shapeless
1个回答
4
投票

首先,它似乎是工作在address以及name在你的评论输出,这是可以预料的。它不是friends工作,因为List[Person]匹配skipCase情况下,它是既非Option[String]List[String]

解决这个问题的最简单的方法是用无形的everywhere组合子。鉴于上面的代码,你可以写:

scala> shapeless.everywhere(trimmer)(person)
res1: Person = Person(Some(john),List(ny, vegas),List(Person(Some(alicia),List(peter),List())))

事实上,你可以完成同样的事情用一个更简单的trimmer实现:

object trimStrings extends Poly1 {
  implicit val stringCase: Case.Aux[String, String] = at[String](_.trim)
}

或等价但更简洁:

import shapeless.poly.->

object trimStrings extends (String -> String)(_.trim)

接着:

scala> shapeless.everywhere(trimStrings)(person)
res5: Person = Person(Some(john),List(ny, vegas),List(Person(Some(alicia),List(peter),List())))

如果你想到底是哪串被修剪过更多的控制,你可以回到你原来的实现,要么添加一个明确的List[Person]情况下,或将匹配类型,如本和递归应用trimmer一个更通用的情况。既然你说你要修剪的所有字符串,虽然everywhere听起来就像是你想要的。

© www.soinside.com 2019 - 2024. All rights reserved.