将代数日期类型列表拆分为分支列表?

问题描述

我是无形的新手,所以这个问题可能很容易。

这是ADT:

sealed trait Test

final case class A() extends Test
final case class B() extends Test
final case class C() extends Test
...
final case class Z() extends Test

是否可以编写没有 繁琐 模式匹配的函数?

def split(lst: List[Test]): List[A] :: List[B] :: ... :: HNil = //

解决方法

在编译时,List的所有元素都具有相同的静态类型Test,因此无法区分元素ABC ...仅使用编译时技术(无形状,类型类,隐式,宏,编译时反射)。这些元素仅在运行时是可区分的,因此您必须使用某种运行时技术(模式匹配,转换,运行时反射)。

Why Does This Type Constraint Fail for List[Seq[AnyVal or String]]

Scala: verify class parameter is not instanceOf a trait at compile time

flatMap with Shapeless yield FlatMapper not found

尝试使用运行时反射将split插入地图

def split(lst: List[Test]): Map[String,List[Test]]  =
  lst.groupBy(_.getClass.getSimpleName)

split(List(C(),B(),A(),C(),A()))
// HashMap(A -> List(A(),A()),B -> List(B(),B()),C -> List(C(),C()))
使用Shapeless +运行时反射将

split转换为HList

import shapeless.labelled.{FieldType,field}
import shapeless.{::,Coproduct,HList,HNil,LabelledGeneric,Poly1,Typeable,Witness}
import shapeless.ops.coproduct.ToHList
import shapeless.ops.hlist.Mapper
import shapeless.ops.record.Values
import shapeless.record._
import scala.annotation.implicitNotFound
    
object listPoly extends Poly1 {
  implicit def cse[K <: Symbol,V]: Case.Aux[FieldType[K,V],FieldType[K,List[V]]] = null
}

// modified shapeless.ops.maps.FromMap
@implicitNotFound("Implicit not found: FromMapWithDefault[${R}]. Maps can only be converted to appropriate Record types.")
trait FromMapWithDefault[R <: HList] extends Serializable {
  // if no value by this key use default,if can't cast return None
  def apply[K,V](m: Map[K,default: V): Option[R]
}
object FromMapWithDefault {
  implicit def hnilFromMap[T]: FromMapWithDefault[HNil] =
    new FromMapWithDefault[HNil] {
      def apply[K,default: V): Option[HNil] = Some(HNil)
    }


  implicit def hlistFromMap[K0,V0,T <: HList]
  (implicit wk: Witness.Aux[K0],tv: Typeable[V0],fmt: FromMapWithDefault[T]): FromMapWithDefault[FieldType[K0,V0] :: T] =
    new FromMapWithDefault[FieldType[K0,V0] :: T] {
      def apply[K,default: V): Option[FieldType[K0,V0] :: T] = {
        val value = m.getOrElse(wk.value.asInstanceOf[K],default)
        for {
          typed <- tv.cast(value)
          rest <- fmt(m,default)
        } yield field[K0](typed) :: rest
      }
    }
}

def split[T,C <: Coproduct,L <: HList,L1 <: HList](lst: List[T])(
  implicit
  labelledGeneric: LabelledGeneric.Aux[T,C],toHList: ToHList.Aux[C,L],mapper: Mapper.Aux[listPoly.type,L,L1],fromMapWithDefault: FromMapWithDefault[L1],values: Values[L1]
): values.Out = {
  val groupped = lst.groupBy(_.getClass.getSimpleName).map { case (k,v) => Symbol(k) -> v }
  fromMapWithDefault(groupped,Nil).get.values
}

测试:

sealed trait Test
final case class A() extends Test
final case class B() extends Test
final case class C() extends Test
final case class Z() extends Test

val res = split(List[Test](C(),A())) 
// List(A(),A()) :: List(B(),B()) :: List(C(),C()) :: List() :: HNil
res: List[A] :: List[B] :: List[C] :: List[Z] :: HNil

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...