scala - 从一种类型的 Monoids HList 派生 HList of zeroes

标签 scala functional-programming shapeless

我正在学习 shapeless,目前我正在尝试创建一个执行以下操作的函数: 给定一个 HList 类型,它返回 NoneHListOption 类型对应给定 HList 类型。

例如:

create[String :: Int :: HNil] // returns None[String] :: None[Int] :: HNil

所以逻辑如下:

def create[A <: HList] {
 type HT = ??? //somehow getting Head type
 type TT = ??? //somehow getting Tail type
 // if HT is HNil  HNil else Option.empty[HT] :: create[TT] 
}

看起来 HTTT 可以由 IsHCons 提供

def createHList[L <: HList](implicit ihc: IsHCons[L]): HList = {
    type HT = ihc.H
    type TT = ihc.T
    //
}

但这引发了两个问题

  1. 如何比较类型?
  2. 编译器找不到用于递归调用的 IsHCons[TT]。 (如何从 IsHCons[L] 获取 ISHCons[TT]HNil 甚至不可能!)

我认为我可以通过为 HNil 和非 HNil 提供隐式来绕过 (1),因此编译器将选择正确的隐式,具体取决于类型。

我在朝着正确的方向前进吗?

鉴于此,可能值得提出更笼统的问题。给定幺半群的 HList,是否有可能推导出零 HList,由给定幺半群的零组成?

谢谢!

最佳答案

为每个 HList 定义 Monoid 实例相当容易,其中每个元素类型都有其 Monoid 实例:

trait Monoid[T] {
  def zero: T
  def plus(t1: T, t2: T): T
}

object Monoid {
  implicit val HNilMonoid: Monoid[HNil] = new Monoid[HNil] {
    def zero = HNil
    def plus(hn1: HNil, hn2: HNil) = HNil
  }
  implicit def HConsMonoid[H, T <: HList](implicit hm: Monoid[H], tm: Monoid[T]): Monoid[H :: T] = 
    new Monoid[H :: T] {
      def zero = hm.zero :: tm.zero
      def plus(ht1: H :: T, ht2: H :: T) = 
        hm.plus(ht1.head, ht2.head) :: tm.plus(ht1.tail, ht2.tail)
    }
}

(其实我希望shapeless能够自动推导出上面的内容,但我不是shapeless的专家)

现在,假设我们在别处定义了 Monoid[Int]Monoid[String],您可以:

implicitly[Monoid[Int :: String :: HNil]].zero

这正是您想要的,即零的 HList

关于scala - 从一种类型的 Monoids HList 派生 HList of zeroes,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37363337/

相关文章:

scala - 如何使用 Spark 结构化流连接到受 Kerberos 保护的 Kafka 集群?

scala - 在Scala中遍历类型 "Any"的集合

Scalaz ·克莱斯利问题

javascript - Javascript/ECMAScript 中函数的作用域是什么?

scala - 如何使用 scala 选项解析器解析通用案例类字段?

scala - HList 上的类型级映射

validation - Scala中的错误处理单子(monad)?尝试与验证

list - Haskell - 如何返回网格中所有元素行的列表

haskell - "No instance for (Ord k)"在 Data.Map.Map 上实现 Functor 时

scala - 一个 HList 到另一个 HList 的隐式转换