高阶kleisli(scala)中的类型相等

时间:2014-10-07 06:57:14

标签: scala category-theory higher-kinded-types

到目前为止的故事 -

type :**:[F[_], G[_]] = ({ type λ[α] = F[G[α]] })

trait HBind[M[_]] extends HFunctor[M] {
  def hbind[F[_], G[_]](f: F ~> (M :**: G)#λ)(implicit MG: Functor[(M :**: G)#λ], F: Functor[F], G: Functor[G]): (M :**: F)#λ ~> (M :**: G)#λ

  def hjoin[F[_]: Functor]: (M :**: (M :**: F)#λ)#λ ~> (M :**: F)#λ

  def hflatMap[F[_], G[_], A](fa: M[F[A]])(f: F ~> (M :**: G)#λ)(implicit MG: Functor[(M :**: G)#λ], F: Functor[F], G: Functor[G]): M[G[A]] = hbind(f)(MG, F, G)(fa)

  def hflatten[F[_]: Functor, A](m: M[M[F[A]]]): M[F[A]] = hjoin(implicitly[Functor[F]])(m)

}

...

trait HMonad[M[_]] extends HBind[M] with HPointed[M]


final class HKleisli[M[_], F[_], G[_]](val run: F ~> (M :**: G)#λ) extends AnyVal {
  import HKleisli.hkleisli
  def apply[A](x: F[A]): M[G[A]] = run(x)
  def hflatMap[K[_]](phi: G ~> ({ type λ[α] = F ~> (M :**: K)#λ })#λ)(implicit M: HMonad[M], H: Functor[(M :**: K)#λ], F: Functor[F], G: Functor[G], K: Functor[K]): HKleisli[M, F, K] =
  hkleisli({
    val psi: (F ~> (M :**: K)#λ) =
      new (F ~> (M :**: K)#λ) {
        def apply[A](fa: F[A]) =
          M.hflatMap(run(fa)) {
            //hole: G ~> [α]M[K[α]]
            val gmk: (G ~> (M :**: K)#λ) =
              new (G ~> (M :**: K)#λ) {
                def apply[A](ga: G[A]) = {
                  val fmk: F ~> (M :**: K)#λ = phi(ga)
                  hkleisli(fmk).run(fa)  // type mismatch; found : fa.type (with underlying type F[A]) required: F[A]
                }
              }
            gmk
          }
      }
    psi
  })

}

object HKleisli {
  def apply[M[_], F[_], G[_]](k: F ~> (M :**: G)#λ) = new HKleisli(k)
  def hkleisli[M[_], F[_], G[_]](k: F ~> (M :**: G)#λ) = apply(k)
}

问题,

现在就这一切而言,有两个目标,首先我有兴趣在scala中实现2类(到目前为止,我已经非常成功{I && #39; m认为程序可能是通过绘制和组合合适类别的图表来设计的.Scala有一个BiCCC 2-Category结构我已经观察过(我至少非常确定)}),第二通用编程, Free Monad是一个更高阶的monad HMonad yoneda和coyoneda有HFunctor个实例,我想知道HKleisli会是什么样的。

现在我遇到了A参数相互遮蔽并创建F [A] -not-F [A]问题的问题。现在我的第一个念头是隐含Leibniz[F[A], F[A']](A'是伪代码)并希望我可以用它来见证[A] F [A] [A']的平等F [A'],但我还没弄清楚它是如何工作的,或者它是否足够,我也想知道我是否刚刚钻走了在这太长的时间里,我错过了一些明显的改写,让我想到的地方,所以我在这里向好人开放。我想尽可能提供任何帮助,并尽可能详细地说明如何实现这一点,我希望能够分享关于更高阶分类抽象的任何想法。

1 个答案:

答案 0 :(得分:0)

所以...还有待测试,但同时,我赢了。请注意与正常kleisli箭头绑定的相似之处。这个问题不是量化的类型平等,好吧,但问题更多的是嵌套,这个版本就像2级更浅,并且与通过加入的出价有很大的相似性,有趣的是我直到后才注意到。我会把这个问题打开一段时间以防万一有人绊倒并且比我有更好的答案。 就/@>而言,只有一点点·代表scala。我直接在~>上定义了它,并为函数写了一个隐式转换。

    final class HKleisli[M[_], F[_], G[_]](val run: F ~> (M :**: G)#λ) extends AnyVal {
      import HKleisli.hkleisli
      def apply[A](x: F[A]): M[G[A]] = run(x)

      final def >=>[K[_]](that: HKleisli[M, G, K])(implicit M: HMonad[M], G: Functor[G], K: Functor[K]): HKleisli[M, F, K] = {
        hkleisli({
          val phi =
            new (F ~> (M :**: K)#λ) {
             def apply[A](fa: F[A]) = {
               M.hbind(that.run)(G, K)(run(fa))
           }
        }
      phi
     })
   }

   final def hbind[K[_]](phi: G ~> ({ type λ[α] = F ~> (M :**: K)#λ })#λ)(implicit M: HMonad[M], K: Functor[K]): HKleisli[M, F, K] = {
   hkleisli({
     val psi =
      new (F ~> (M :**: K)#λ) {
      def apply[A](fa: F[A]) =
        M.hjoin(K)(M.map(M.transmap[G, ({ type λ[α] = F ~> (M :**: K)#λ })#λ](phi)(run(fa))) { (nt: F ~> (M :**: K)#λ) => nt(fa) })
     }
     psi
   })
  }

  final def local[X[_]](f: X ~> F) = hkleisli { 
    val phi = 
      new (X ~> (M:**:G)#λ) {
       def apply[A](x: X[A]) =
        (f /@>[(M:**:G)#λ] run)(x)
    }
    phi
  }
}

object HKleisli {
  def apply[M[_], F[_], G[_]](k: F ~> (M :**: G)#λ) = new HKleisli(k)

  def hkleisli[M[_], F[_], G[_]](k: F ~> (M :**: G)#λ) = apply(k)

  type HKleisliAr[M[_]] = ({ type λ[φ[_], ψ[_]] = HKleisli[M, φ, ψ] })

  def hkIdentity[M[_], F[_]](implicit M: HMonad[M], F: Functor[F]): HKleisli[M, F, F] =
    hkleisli(M.hpoint(F))

  implicit def category[M[_]: HMonad]: HCategory[HKleisliAr[M]#λ] =
    new HCategory[HKleisliAr[M]#λ] {
      def identity[F[_]: Functor] = hkIdentity[M, F]
      def composition[A[_]: Functor, B[_]: Functor, C[_]: Functor](g: HKleisli[M, B, C])(f: HKleisli[M, A, B]) =
        f >=> g
    }
   }