从一种类型的 Monoids HList 派生 HList of zeroes
Deriving HList of zeroes from a type of HList of Monoids
我正在学习 shapeless,目前我正在尝试创建一个执行以下操作的函数:
给定一个 HList
的类型 returns None
的 HList
,Option
类型对应给定的 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]
}
看起来 HT
和 TT
可以由 IsHCons
提供
def createHList[L <: HList](implicit ihc: IsHCons[L]): HList = {
type HT = ihc.H
type TT = ihc.T
//
}
但这会引发两个问题
- 如何比较类型?
- 编译器找不到
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
个零。
我正在学习 shapeless,目前我正在尝试创建一个执行以下操作的函数:
给定一个 HList
的类型 returns None
的 HList
,Option
类型对应给定的 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]
}
看起来 HT
和 TT
可以由 IsHCons
def createHList[L <: HList](implicit ihc: IsHCons[L]): HList = {
type HT = ihc.H
type TT = ihc.T
//
}
但这会引发两个问题
- 如何比较类型?
- 编译器找不到
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
个零。