代码之家  ›  专栏  ›  技术社区  ›  André Luiz Ferreira Pinto

将F-代数[F,A]合成为F-代数[F,Seq[A]]

  •  2
  • André Luiz Ferreira Pinto  · 技术社区  · 7 年前

    我正在尝试组成F-代数,如 this page . 不同之处在于,与使用元组组合不同,如下所示:

    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 帮助

    2 回复  |  直到 7 年前
        1
  •  3
  •   Jasper-M    4 年前

    如果我可以对您的约束进行一些细微的修改,我可以找到一个实现:

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

    我需要 Traverse 实例,以便能够对 F[Seq[A]] 到a Seq[F[A]] .

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

        2
  •  3
  •   V-Lamp    7 年前

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

    代数的形状就像科克莱斯利:

      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)