8

Trong khi đọc các mô tả về functors trên blog này:Scala - Cách sử dụng Functors trên các loại phi chức năng?

https://hseeberger.wordpress.com/2010/11/25/introduction-to-category-theory-in-scala/

có một định nghĩa chung của functor và cụ thể hơn một:

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) 
} 

Rõ ràng điều này có nghĩa functors có thể được sử dụng với khác loại cao hơn bên cạnh các đối tượng chức năng. Có thể ai đó xin vui lòng đưa ra một ví dụ hoặc giải thích làm thế nào hoặc tại sao hoặc trong những kịch bản đó sẽ được thực hiện? Cụ thể, việc thực hiện khác của GenericFunctor là gì trong Scala - sử dụng một hàm tạo kiểu khác từ Hàm? Cảm ơn!

EDIT:

Chỉ cần làm rõ:

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) 

Chỉ cần làm rõ, theo sự hiểu biết ListFunctor tôi thực hiện 1-arg fmap trong GenericFunctor trong khi các mã trong bảng điểm repl gọi fmap trong Trait Functor, mà lần lượt gọi một thực hiện fmap (ví dụ như trong ListFunctor).

Điều này không thay đổi câu hỏi tổng thể, chỉ nghĩ rằng nó sẽ giúp mọi người cố gắng cung cấp câu trả lời. Mọi thông tin chi tiết được cung cấp sẽ được đánh giá cao.

Trả lời

7

Trong ví dụ của bạn Functor là một endofunctor trong hạng mục các loại Scala với Function1 như mũi tên.

Có các danh mục khác. Ví dụ, hãy tưởng tượng một thể loại trong đó các đối tượng là kiểu Scala, và có một mũi tên A >~> B nếu B là một kiểu con của A. Thể loại này trong Scalaz được gọi là Liskov.Có một "quên" functor từ danh mục Liskov vào ngạch 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) 
} 

Lưu ý rằng bạn có thể xây dựng một số functors thú vị bằng cách sửa chữa một hoặc nhiều biện minh cho khả GenericFunctor. Ví dụ ...

Một liên tục functor bản đồ tất cả các đối tượng trong một nhóm đến một đối tượng duy nhất trong một:

type ConstantFunctor[->>[_, _], ->>>[_, _], C] = 
    GenericFunctor[->>,->>>,({type F[x] = C})#F] 
// def fmap[A, B](f: A ->> B): C ->>> C 

Một endofunctor bản đồ một thể loại cho chính nó:

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

An identity functor ánh xạ mọi đối tượng và mũi tên đến chính nó:

type IdentityFunctor[->>[_, _]] = EndoFunctor[->>, ({type F[x] = x})#F] 
// def fmap[A, B](f: A ->> B): A ->> B 

Và tất nhiên, đặc điểm Functor của bạn chỉ là một EndoFunctor trong danh mục Function1.

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

Bạn có thể tưởng tượng một functor mà thang máy một thể hiện của Either[A,B] thành một Either[F[A],F[B]] nơi F có thể là một List, Option vv

EDIT dụ Thực hiện:

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 Một (có thể hữu ích) ví dụ là với một functor với đi từ một PartialFunction (loại ->>) đến một Function (loại ->>>):

trait PartialFunctor[F[_]] 
extends GenericFunctor[PartialFunction,Function,F] { 
    final def fmap[A, B](as: F[A])(f: PartialFunction[A,B]): F[B] = 
    fmap(f)(as) 
} 

object OptionFunctor extends PartialFunctor[Option] { 
    def fmap[A,B](f: PartialFunction[A,B]): Option[A] => Option[B] = 
    (opt:Option[A]) => opt match { 
     case Some(a) => f.lift(a) 
     case None => None 
    } 
} 

object ListFunctor extends PartialFunctor[List] { 
    private def mapPartial[A,B](f: PartialFunction[A,B], as: List[A]): List[B] = 
    as match { 
     case Nil => Nil 
     case h :: t => if(f isDefinedAt h) f(h) :: mapPartial(f, t) 
        else mapPartial(f, t) 
    } 

    def fmap[A,B](f: PartialFunction[A,B]): List[A] => List[B] = 
    (lst:List[A]) => mapPartial(f, lst) 

} 

ví dụ thứ hai này cho phép để thực hiện các hoạt động collect theo quy định tại các bộ sưu tập Scala:

def collect[A,B,F[_]](as: F[A]) 
        (pf: PartialFunction[A,B]) 
        (implicit functor: PartialFunctor[F]) = 
    functor.fmap(as)(pf) 
+0

Tôi không nghĩ rằng hàm giả là một hàm. Tôi không thể thấy cách bạn triển khai một danh mục. – Anonymous

Các vấn đề liên quan