将 F-Algebra[F, A] 组合成 F-Algebra[F, Seq[A]]

Composing F-Algebra[F, A] to F-Algebra[F, Seq[A]]

我正在尝试像 this page 中那样编写 F 代数。不同之处在于,不是用元组组合,而是像这样:

type FAlgebra[F[_], A] = F[A] => A

def algebraZip[F[_], A, B](fa: FAlgebra[F, A], fb: FAlgebra[F, B])
                      (implicit F: Functor[F]): FAlgebra[F, (A, B)] =
  fab => {
    val a = fa(fab.map(_._1))
    val b = fb(fab.map(_._2))
    (a, b)
  }

我想使用 Seq,像这样:

def algebraSeq[F[_], A](fa: FAlgebra[F, A])
                       (implicit F: Functor[F]): FAlgebra[F, Seq[A]] = ???

可能吗?我需要什么?或者使用 shapeless HList 会有帮助吗?

如果我可以对你的约束做一些细微的改动,我可以找到一个实现:

def algebraSeq[F[_]: Traverse, A](fa: FAlgebra[F, A]): FAlgebra[F, Seq[A]] = 
  fseq => fseq.sequence.map(f => fa(f))

我需要 Traverse 实例才能将 F[Seq[A]] 排序为 Seq[F[A]]

过去您必须为 List 而不是 Seq 编写此函数,因为没有 Applicative[Seq] 实例。但是由于添加了 immutable.Seq 的 cats 2.3.0 实例(这是 Scala 2.13 中的默认 scala.Seq)。

完全同意Jasper的回答。但我喜欢概括 ;)

你的代数形状就像 CoKleisli:

  import cats._
  import cats.implicits._
  import cats.data.Cokleisli
  type FAlgebra[F[_], A] = Cokleisli[F, A, A]

  def nestEffect[F[_], A, B, G[_]](coKleisli: Cokleisli[F, A, B])
                            (implicit F: Traverse[F], G: Applicative[G]): Cokleisli[F, G[A], G[B]] =
    Cokleisli((fga: F[G[A]]) => F.sequence[G, A](fga).map(coKleisli.run))

    def algebraSeq[F[_], A](fa: FAlgebra[F, A])
                         (implicit F: Traverse[F]): FAlgebra[F, List[A]] = 
      nestEffect[F, A, A, List](fa)