微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决将代数日期类型列表拆分为分支列表?

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

这是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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。