我试图通过point
和bind
实现为无形HList
定义一个Monad
(scalaz)。第一个问题是HList
trait 不是类型构造函数,但可以用类型 lambda 解决,point
很简单,但我找不到适合bind
的实现,我想我需要一些带有一些Aux/Mapper
技巧的 Poly1
类型的函数,但 shapeless 的那一面对我来说仍然是黑暗的。 HList
具有成为Monad的所有功能,例如简单的List,那么是否可以从Scalaz实现一个?
幺半群是具有一些遵守特定定律的操作的集合。您正在考虑哪些元素作为可能的HListM[A]
?如果你声明HListM[A] = HList
,即任何HList
,那么你很快就会发现你不能用f: A => B
map
,除非把所有map
都视为identity
,并且你已经重新发明了相当无趣的monad Id
(有一些额外但惰性的居民)。
我们可以用 HListM[A] = A :: ... :: A :: HNil
类型制作一个 monad(尽管即使在 Scala 中实际表达该类型也是一个挑战 - 你需要一个辅助特征 trait CopiesOf[N <: Nat, A] {type Out <: HList
},implicit
s 来提供这方面的实例,然后是一个存在主义来实际编写它(CopiesOf[N, A]#Out forSome {type N <: Nat}
))。为此编写monad操作是可能的,尽管您需要在操作点需要像Prepend
这样的无形辅助类,因为在Scala中没有真正的方法来表达"forall"类型 - 你可以为_0
和Succ[N]
声明你的类型的实例,但没有办法向编译器证明任何N <: Nat
都有一个实例, 您只需在需要使用隐式时需要它们。
但是经过大量的工作,你最终会得到一些同构的东西List[A]
;为什么不直接使用List[A]
来表示这种情况呢?