从一类Hoid of Monoids中导出零的HList

I S*_*ces 3 functional-programming scala shapeless

我学习不成形,目前我试图创建一个具有以下功能:给定一个类型的HList它返回HListNoneS,与Option相应的给定类型的HList类型.

例如:

create[String :: Int :: HNil] // returns None[String] :: None[Int] :: HNil
Run Code Online (Sandbox Code Playgroud)

所以逻辑如下:

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] 
}
Run Code Online (Sandbox Code Playgroud)

看起来像HTTT可以提供IsHCons

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

但这引发了两个问题

  1. 如何比较类型?
  2. 编译器找不到IsHCons[TT]递归调用.(如何获得ISHCons[TT]IsHCons[L]?这不是甚至有可能HNil!)

我认为我可以绕过(1),通过提供implicits for HNil和non HNil,因此编译器会根据类型选择正确的隐式.

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

鉴于此,可能值得提出更一般的问题.鉴于HListMonoids,是否有可能导出零HList,由给出幺半群的零组成?

谢谢!

ghi*_*hik 6

MonoidHList每个元素类型的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)
    }
}
Run Code Online (Sandbox Code Playgroud)

(实际上,我希望无形能够自动导出上述内容,但我不是无形的专家)

现在,假设我们有Monoid[Int]Monoid[String]其他地方定义,你可以:

implicitly[Monoid[Int :: String :: HNil]].zero
Run Code Online (Sandbox Code Playgroud)

这正是你想要的,即一个HList零.