从一个类型的幺半群HList中获得零的HList [英] Deriving HList of zeroes from a type of HList of Monoids

查看:98
本文介绍了从一个类型的幺半群HList中获得零的HList的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习不成形,目前我正在尝试创建一个执行以下操作的函数:
给定类型 HList 它返回> HList s,其中选项例如:

  create [String :: Int :: HNil] //返回None [String] :: None [Int] :: HNil 

所以逻辑如下:

  def create [A< ;: HList] {
type HT = ??? //以某种方式获取头像类型
类型TT = ??? //以某种方式得到Tail type
//如果HT是HNil HNil else Option.empty [HT] :: create [TT]
}

看起来像 HT TT 可以由 IsHCons

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

但是这会增加两个问题


  1. 如何比较类型?

  2. 编译器无法找到用于递归调用的 IsHCons [TT] 。 (如何从 IsHCons [L] 获取 ISHCons [TT] ?甚至不可能为!)

我认为我可以避开(1)对于 HNil 和非 HNil ,所以编译器会根据类型选择正确的隐式。



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

鉴于此,可能值得多提一些一般性问题。考虑到Monoid的 HList ,是否可以派生出零 HList ,其中包含给零单元的零?



谢谢!

解决方案

每个 HList 的Monoid 实例,其中每个元素类型都有它的 Monoid 实例:

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


Monoid {
implicit val HNilMonoid:Monoid [HNil] = new Monoid [HNil] {
def zero = HNil
def (hn1:HNil,hn2:HNil)= HNil
}
隐含def HConsMonoid [H,T <:HList](隐式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)
}
}

(其实,我wo现在,假设我们有 Monoid,那么我们就可以自动地得到上述结果,但是我并不是无形中的专家)

在其他地方定义了[Int] Monoid [String] ,您可以:

 隐式地[Monoid [Int :: String :: HNil]]。zero 

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


I am learning shapeless, and currently I am trying to create a function that does the following: given a type of an HList it returns the HList of Nones, with the Option types corresponding to given HList type.

For instance:

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

So the logic is the following:

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] 
}

Looks like the HT and TT can be provided byIsHCons

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

But that rises two problems

  1. How to compare types?
  2. Compiler can not find IsHCons[TT] for recursive call. (How to get ISHCons[TT] from IsHCons[L]? It is not even possible for HNil!)

I think that I can get around the (1), by providing implicits for HNil and non HNil, so the compiler will pick up the right implicit, depending on the type.

Am I moving towards the right direction?

Given that, may be it is worth to ask more general question. Given the HList of Monoids, is it possible to derive zero HList, consisting of zeros of give monoids?

Thanks!

解决方案

It's fairly easy to define Monoid instance for every HList where each element type has its Monoid instance:

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)
    }
}

(actually, I would expect shapeless to be able to derive the above automatically, but I'm not an expert on shapeless)

Now, assuming that we have Monoid[Int] and Monoid[String] defined elsewhere, you can just:

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

which is exactly what you want, i.e. a HList of zeros.

这篇关于从一个类型的幺半群HList中获得零的HList的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆