Function Scala——如何在非函数类型上使用函子?

Function Scala——如何在非函数类型上使用函子?,function,scala,functional-programming,functor,category-theory,Function,Scala,Functional Programming,Functor,Category Theory,阅读此博客上的函子说明时: 函子有一个通用定义,还有一个更具体的定义: trait GenericFunctor[->>[_, _], ->>>[_, _], F[_]] { def fmap[A, B](f: A ->> B): F[A] ->>> F[B] } trait Functor[F[_]] extends GenericFunctor[Function, Function, F] { final def fmap

阅读此博客上的函子说明时:

函子有一个通用定义,还有一个更具体的定义:

trait GenericFunctor[->>[_, _], ->>>[_, _], F[_]] {
  def fmap[A, B](f: A ->> B): F[A] ->>> F[B]
}
trait Functor[F[_]] extends GenericFunctor[Function, Function, F] {
  final def fmap[A, B](as: F[A])(f: A => B): F[B] =
    fmap(f)(as)
}
显然,这意味着函子可以与函数对象之外的其他更高级类型一起使用。有人能举个例子或者解释一下怎么做,为什么做,或者在什么情况下做?也就是说,在Scala中,GenericFunctor的另一个实现是什么——它使用与函数不同的类型构造函数?谢谢

编辑:

我想澄清一下:

object Functor {

  def fmap[A, B, F[_]](as: F[A])(f: A => B)(implicit functor: Functor[F]): F[B] =
    functor.fmap(as)(f)

  implicit object ListFunctor extends Functor[List] {
    def fmap[A, B](f: A => B): List[A] => List[B] =
      as => as map f
  }
}
scala> fmap(List(1, 2, 3))(x => x + 1)
res0: List[Int] = List(2, 3, 4)
只是澄清一下,根据我的理解,ListFunctor在GenericFunctor中实现了1-arg fmap,而repl转录本中的代码调用了特征函数中的fmap,特征函数又调用了fmap实现(例如,在ListFunctor中)


这并没有改变整个问题,只是认为这会帮助人们提供答案。您可以想象一个函子,它将
或[a,B]
的一个实例提升为
或[F[a],或[F[B]
,其中
F
可以是
列表
选项
,等等

编辑实施示例:

trait GenericFunctor[->>[_, _], ->>>[_, _], F[_]] {
  def fmap[A, B](f: A ->> B): F[A] ->>> F[B]
}

trait EitherFunctor[F[_]] extends GenericFunctor[Either,Either,F]

object ListFunctor extends EitherFunctor[List] {
  def fmap[A,B]( f: Either[A,B] ): Either[List[A],List[B]] = 
    f match {
      case Left(a) => Left( List(a) )
      case Right(b) => Right( List(b) )
    }
}
EDIT2另一个(可能有用)示例是一个函子,它从
部分函数
(type
->
)变为
函数
(type
->
):

第二个示例允许实现Scala collections中定义的
collect
操作:

def collect[A,B,F[_]]( as: F[A] )
                     ( pf: PartialFunction[A,B] )
                     ( implicit functor: PartialFunctor[F] ) = 
  functor.fmap( as )( pf )
是此类示例的良好来源(在Haskell中)。从以下内容部分转换其中一个实例:


在您的示例中,
Functor
是Scala类型中的一个内函子,其
Function1
为箭头

还有其他类别。例如,假设一个类别中的对象是Scala类型,如果
B
a
的子类型,则有一个箭头
a>~>B
。中的这一类别称为。从
Liskov
类别到
Function1
类别有一个“健忘”函子:

import scalaz._
import Scalaz._
trait Forget[F[-_]] extends GenericFunctor[>~>, Function1, F] {
  def fmap[A, B](f: A >~> B): F[A] => F[B] = fa => f.subst(fa)
}
请注意,通过将一个或多个参数固定到
GenericFunctor
,可以构建一些有趣的函子。例如

常量函子将一个类别中的每个对象映射到另一个类别中的单个对象:

type ConstantFunctor[->>[_, _], ->>>[_, _], C] =
  GenericFunctor[->>,->>>,({type F[x] = C})#F]
// def fmap[A, B](f: A ->> B): C ->>> C
内函子将类别映射到自身:

type EndoFunctor[->>[_, _], F[_]] = GenericFunctor[->>, ->>, F]
// def fmap[A, B](f: A ->> B): F[A] ->> F[B]
type IdentityFunctor[->>[_, _]] = EndoFunctor[->>, ({type F[x] = x})#F]
// def fmap[A, B](f: A ->> B): A ->> B
标识函子将每个对象和箭头映射到自身:

type EndoFunctor[->>[_, _], F[_]] = GenericFunctor[->>, ->>, F]
// def fmap[A, B](f: A ->> B): F[A] ->> F[B]
type IdentityFunctor[->>[_, _]] = EndoFunctor[->>, ({type F[x] = x})#F]
// def fmap[A, B](f: A ->> B): A ->> B
当然,你的
函子
特征只是
Function1
类别中的
EndoFunctor

type Functor[F[_]] = EndoFunctor[Function1, F]
// def fmap[A, B](f: A => B): F[A] => F[B]

我认为这两个函子都不是函子。我看不出您如何实现这两个类别。