【问题标题】:Converting a Scala Iterable[T] to an Option[Iterable[S]], populated if ALL the T are instances of S?将 Scala Iterable[T] 转换为 Option[Iterable[S]],如果所有 T 都是 S 的实例,则填充?
【发布时间】:2021-09-09 01:10:53
【问题描述】:

我有一种模糊的感觉,这种方法可能存在(可能在Cats?) - 目的是转为Iterable[T]Set[T]是我真正感兴趣的) 转换为Option[Iterable[S]] - 结果是:

  • Some[Iterable[S]] :如果Iterable[T] 中的所有 条目是S 的实例
  • None :如果Iterable[T] 中的任何条目不是S 的实例

我知道在 Cats 中已经有一种类似的方法,由 Alternative 授予 - 它是 separate

import cats.implicits._
import alleycats.std.set._

val stringsAndInts: Set[Either[String, Int]] = Set(Right(6),Left("Foo"))
val (strings: Set[String], ints: Set[Int]) = stringsAndInts.separate

...这对Set[Either[A,B] 很有效——但对于这个问题,我只对任何旧的Set[T] 感兴趣。

collect 呢?

此代码使用 Scala 标准库方法 collect 将编译 - 但请注意,它始终会生成 Set[S] - 即使某些 setOfT 不是 S 的实例:

val setOfT: Set[T] = ???
val setOfS: Set[S] = setOfT.collect {case s: S => s}

【问题讨论】:

  • 如果你有任意类型,由于类型擦除,这不能开箱即用。您要么需要为某些类型的子集编写特定的方法,要么创建自己的 typeclass 来验证数据。 - 或者您可以使用运行时反射并为类型擦除打开错误之门。

标签: scala casting scala-collections scala-cats


【解决方案1】:

考虑无形类型安全铸造

import shapeless._
import syntax.typeable._

val xs: Set[Any] = Set("picard", "worf")

xs.cast[Set[Int]]
// res1: Option[Set[Int]] = None

xs.cast[Set[String]]
// res2: Option[Set[String]] = Some(value = Set("picard", "worf"))

如果您希望拥有与 collect 类似的功能并且在类路径中已经有了猫,那么这里是单线

import alleycats.std.set._
animals.map(implicitly[ClassTag[Dog]].unapply).sequence

Option[Set[Dog]] 的类型。

【讨论】:

【解决方案2】:

正如 Luis Miguel Mejía Suárez 在评论中指出的那样,由于类型擦除,我想要的方法无法用于任意类型。

最后,我写了这样的代码:

val animals: Set[Animal] = ???
val optDogs: Option[Set[Dog]] = animals.foldLeft(Option(Set.empty[Dog])) {
  case (oDogs, dog: Dog) => oDogs.map(_ + dog)
  case _ => None
}

...很高兴看到更好的实现!

【讨论】:

  • 你可以只做aminals.collect { case dog: Dog => dog } 并检查它是否为非空。你也可以做animals.traverse { case dog: Dog => Some(dog); case _ => None } 或者你可以使用你自己的 Typeclass 来概括它 trait Is[T, U] { def check(t: T): Option[U] } 最终会做相同的match 并且可以与相同的traverse 一起使用,但它似乎 *Shapeless 已经为你解决了 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-07
  • 1970-01-01
  • 2010-10-14
  • 2013-12-06
  • 2020-02-25
  • 2014-03-24
  • 2011-04-04
相关资源
最近更新 更多