在Scala中的高阶Functor

9

我一直在尝试将函数子的直觉推向极限,通过定义高阶函数子来实现,即一个F,它以第一阶类型作为类型参数,并将第一阶类型上的函数提升到这个更高的上下文中,在Scala中实现类似于:

trait Functor1[F[_[_]] {
    def hmap[X[_], Y[_]] : (X ~> Y) => F[X] => F[Y]
}

我一直在尝试定义正常函子的一些可导地图函数,例如:

trait Functor[F[_]] {
  def map[A, B] : (A => B) => F[A] => F[B]

  // there's a few more besides this that are map derivable
  def distribute[A,B](fab: F[(A, B)]): (F[A], F[B])
}

但是我不会写任何类型检查的代码... 我只是在尝试,想知道是否有比我更聪明的人已经走过这条路

在Scala中可以定义高阶函子吗?如果不能,那么在Haskell中呢?


4
在 Haskell 中:http://hackage.haskell.org/package/category-extras-0.53.5/docs/Control-Functor-HigherOrder.html - Nikita Volkov
正如你可能已经知道的那样,scalaz是一个功能强大的Scala函数式编程库。尝试查看scalaz中Functor实现的文档 - Mohammad Dashti
我认为distribute不是Functor上的方法 - 它是自己的类型类:http://hackage.haskell.org/package/distributive-0.1.2/docs/Data-Distributive.html - dyross
我发现当我被函数子困扰时,我要么去看Haskell,要么如果我真的想困惑,我就去看ScalaZ源代码。 - Totoro
“可映射函数”是什么?快速的谷歌搜索并没有显示出我认为相关的任何内容。 - Boyd Stephen Smith Jr.
2个回答

3

不确定你的目标是什么,但是这个代码进行了类型检查。

  import scala.language.higherKinds

  trait Functor1[F[G[_]]]{
    def hmap[X[_], Y[_]]:(X ~> Y) => F[X] => F[Y] 
  }

  case class FId[Z,F[_]](f:F[Z])


  implicit def Functor1Id[Z] = new Functor1[({type L[G[_]]=FId[Z,G]})#L]{
    def hmap[X[_], Y[_]]:(X ~> Y) => FId[Z,X] => FId[Z,Y]= ??? 
  }

我添加了Z参数,因为我想避免存在性问题并且不得不使用“类型λ”技巧。

您是否想为“functor of a functor”定义地图?我认为我做了类似的事情(在这里称为组合):

case class Comp[F[_],G[_],Z](unComp:F[G[Z]])
implicit def fcomp[F[_], G[_]](implicit ff:Functor[F], fg:Functor[G])=new Functor[({ type abs[A]=Comp[F,G,A]})#abs]{
  def fmap[A,B](fga:Comp[F,G,A])(f: A => B):Comp[F,G,B]= Comp(ff.fmap(fga.unComp)(fg.fmap(_)(f)))
}

我一直在玩弄scala-reggen中的函数子,但我认为我并不聪明,因为我主要是靠摸索来做的(并查看了Scalaz以获得灵感)


1
/** Higher order functor */
trait HFunctor[F[_]] {
  def ffmap[G[_]: Functor, A, B](f: A => B): F[G[A]] => F[G[B]]
  def hfmap[G[_], H[_]](t: G ~> H): ({type λ[α] = F[G[α]]})#λ ~> ({type λ[α] = F[H[α]]})#λ
}

trait Functor[F[_]] { self =>

  def fmap[A, B](f: A => B): F[A] => F[B]

  // derived

  def map[A, B](x: F[A])(f: A => B): F[B]          = fmap(f)(x)
  def strengthL[A, B]: A => F[B] => F[(A, B)]      = a => f => fmap((x: B) => (a, x))(f)
  def strengthR[A, B]: F[A] => B => F[(A, B)]      = f => b => fmap((x: A) => (x, b))(f)
  def compose[G[_]](implicit e: Functor[G]): Functor[({ type λ[α] = F[G[α]]})#λ] =
    new Functor[({ type λ[α] = F[G[α]]})#λ] {
      def F = self;
      def G = e
      def fmap[A, B](f: A => B) = F.fmap(G.fmap(f))
    }

}

object Functor {
  @inline def apply[F[_]: Functor]: Functor[F] = iev
}

trait Coyoneda[F[_], A] { co =>

  type I

  def fi: F[I]

  def k: I => A

  final def run(implicit F: Functor[F]): F[A] = F.fmap(k)(fi)

  final def map[B](f: A => B): Coyoneda.Aux[F, B, I] =
   Coyoneda(fi)(f compose k)

  final def trans[G[_]](phi: F ~> G): Coyoneda[G, A] =
   Coyoneda(phi(fi))(k)
}

object Coyoneda {

  type Aux[F[_], A, B] = Coyoneda[F, A] { type I = B }

  def apply[F[_], B, A](x: F[B])(f: B => A): Aux[F, A, B] =
    new Coyoneda[F, A] {
      type I = B
      val fi = x
      val k = f
   }

implicit def coyonedaFunctor[F[_]]: Functor[({ type λ[α] = Coyoneda[F, α] })#λ] =
  new Functor[({ type λ[α] = Coyoneda[F, α] })#λ] {
    def fmap[A, B](f: A => B): Coyoneda[F, A] => Coyoneda[F, B] =
      x => apply(x.fi)(f compose x.k)
  }

implicit def coyonedaHFunctor: HFunctor[({ type λ[F[_]] = ({ type λ[α] = Coyoneda[F, α] })#λ })#λ] =
  new HFunctor[({ type λ[F[_]] = ({ type λ[α] = Coyoneda[F, α] })#λ })#λ] {
    def ffmap[G[_]: Functor, A, B](f: A => B): Coyoneda[G, A] => Coyoneda[G, B] = _.map(f)
    def hfmap[F[_], G[_]](t: F ~> G): (({ type λ[α] = Coyoneda[F, α] })#λ ~> ({ type λ[α] = Coyoneda[G, α] })#λ) = 
    new (({ type λ[α] = Coyoneda[F, α] })#λ ~> ({ type λ[α] = Coyoneda[G, α] })#λ) {
    def apply[A](x: Coyoneda[F, A]) = x.trans(t)
  }
}

def liftCoyoneda[F[_], A](fa: F[A]): Coyoneda[F, A] = apply(fa)(x => x)

def lowerCoyoneda[F[_]: Functor, A](c: Coyoneda[F, A]): F[A] = c.run

}

我得测试一下并稍微解释一下我的过程,但这就是几周前我定下来的东西,只是没抽出时间来发布... - Mzk Levi
好的,也许可以写一篇博客文章? :) - GClaramunt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接