Functor و Applicative

scala

#1

چندساختار خیلی کاربردی و معروف در functional programming با تایپ ستاتیک وجود داره که ریشه در ریاضی category theory دارند
من برخی از اینها رو توضیح میدم

Functor
همه با functor آشنا هستن این ساختاری هستش که map داره و چند قانون دیگه که من الان توضیح نمیدم
map یک type سازنده A مثله لیست Int میگیره و یک function از type A به یک type دیگه مثله B میگیره و function روی تمامه ازای سازنده
اجرا میکنه و نتیجه به شکله type سازنده B برمیگردونه

List(1,2,3).map(x=> x*2)

//List(2,4,6) 

Some(2).map(println)

// 2

بصورت کلی

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

ترکیب پذیری functor ها

فرض کنید ما یک لیست از option های int داریم و میخواهیم عددهای داخل این لیست option دو برابر کنیم

راه اول :

val myList = List(Some(1), Some(2), None)
myList.map{ opt => opt.map { num => num * 2 } }

// res4: List[Option[Int]] = List(Some(2), Some(4), None)

ما اینجا ۲ بار داریم map میکنیم که خیلی خوب نیست
راه دوم برای اینکه بتونیم یک بار map کنیم functor لیست را با option ترکیب میکنیم

من از کتابخانه cats استفاده میکنم که اتوماتیک این ساختار هارو برام بسازه

import cats._
import cats.implicits._

val listOptionFunctor = Functor[List].compose(Functor[Option])

listOptionFunctor.map(myList)( x => x *2) 

// List[Option[Int]] = List(Some(2), Some(4), None)

Applicative

یک ساختار که یک type معمولی با function به نام pure وارد type سازنده میکنه

1.pure[List] 

// List(1)

import cats.Functor

trait Applicative[F[_]] extends Functor[F] {
  def ap[A, B](ff: F[A => B])(fa: F[A]): F[B]

  def pure[A](a: A): F[A]

  def map[A, B](fa: F[A])(f: A => B): F[B] = ap(pure(f))(fa)
}

معادل UML برای زبانهای فانکشنال : Category theory