Аппликативы

Robert Gubin
Jul 30, 2017 · 2 min read

Сегодня поговорим об аппликативных функторах и о том какие проблемы они решают.
Для понимания лучше прочитать статью о функторах: https://medium.com/@gubinrobert/%D1%84%D1%83%D0%BD%D0%BA%D1%82%D0%BE%D1%80%D1%8B-f9f826539a0d
Начнем с проблематики: довольно часто на практике нужно применить функцию о множестве аргументов к содержимому множества контейнеров. Например просуммировать их содержимое. Хотелось бы что-то вроде:
map2(Maybe(2), Maybe(3), ((a, b) => a + b))
В сущности это становится возможным благодаря интересному трюку — решению проблемы следующего вида:

def ap[F[_], A, B](f: F[A => B])(v: F[A]): F[B]

Как видно из определения — морфизм, поднятый в категорию F, это то же самое что и морфизм из F[A] => F[B].
Итак, что это нам даёт? И как поднять функцию в категорию F?
Ответ на этот вопрос может быть понятен из следующего примера:

Стоит обратить внимания что функция f — по сути каррированная функция от двух аргументов. Результатом её применения посредством функции map будет являться функция, но уже от одного аргумента.
Таким образом мы и поднимаем (lift) функцию. Можно посмотреть на это через призму lift:

Как видно результаты идентичны.
Теперь, когда у нас есть функция вида Maybe[Int => Int] как же использовать её?
По сути нам нужно как-то сделать из Maybe[Int => Int] функцию вида Maybe[Int] => Maybe[Int].
Тут на помощь и приходят аппликативы:

Далее мы напишем код, соответствующий аппликативу и рассмотрим еще несколько функций, которые можно выразить в терминах ap.

Из определения видно следующее:

  1. для того чтобы быть аппликативным функтором нужно сначала стать функтором
  2. аппликативный функтор требует наличия функции pure, которая поднимает объект в категорию для которой определен функтор
  3. в терминах ap можно выразить такие интересные функции как product и map2.

функция product — делает из двух контейнеров один с кортежем внутри
функция map2 — композиция функций product и map, именно та, которую мы и хотели в начале статьи.

Теперь напишем реализацию этого трейта:

По сути всё что мы делаем — это берем функцию и применяем её к значению, если функции нет, то и применить к значению мы ничего не сможем,
соответственно и все функторные законы должны исполняться:

Таким образом аппликативные функторы — невероятно полезная сущность, благодаря которой можно избавиться от кучи лишнего кода и сделать решение более лаконичным и понятным.

Материалы:
http://learnyouahaskell.com/functors-applicative-functors-and-monoids#applicative-functors

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade