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

时间:2016-05-21 13:05:39

标签: scala functional-programming shapeless

我正在学习无形,目前我正在尝试创建一个执行以下操作的函数: 给定一种HList类型,它会返回HList NoneOptionHList类型与给定的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] 
}

所以逻辑如下:

HT

TT

看起来可以提供IsHConsdef createHList[L <: HList](implicit ihc: IsHCons[L]): HList = { type HT = ihc.H type TT = ihc.T // }
IsHCons[TT]

但这会引发两个问题

  1. 如何比较类型?
  2. 编译器无法找到ISHCons[TT]进行递归调用。 (如何从IsHCons[L]获取HNilHNil甚至不可能!{/ li>

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

    我是否朝着正确的方向前进?

    鉴于此,可能值得提出更一般的问题。鉴于Monoids的HList,是否有可能导出零openssl ecparam -genkey -name secp256k1 -noout -outform DER -out private.key openssl ec -inform DER -in private.key -noout -text openssl dgst -sha256 -hex -sign private.key -keyform DER ,由给出幺半群的零组成?

    谢谢!

1 个答案:

答案 0 :(得分:6)

为每个Monoid定义HList实例相当容易,其中每个元素类型都有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)
    }
}

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

现在,假设我们在其他地方定义了Monoid[Int]Monoid[String],您可以这样做:

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

这正是你想要的,即HList零。