Аппликативные функторы, кроме монад и ZipList? - PullRequest
14 голосов
/ 23 января 2010

Двумя хорошо известными примерами аппликативов являются монады и почтовые индексы.Есть ли другие примеры?

Ответы [ 7 ]

11 голосов
/ 23 января 2010

С Время летит как аппликативный функтор Конор МакБрайд:

Структурные копы заметят, что De - это еще один пример аппликативного функтора, который не является монадой - объединение принесло бы вещи из далекого будущего в ближайшее, и это лучше было бы невозможно. Однако, если аппликативные функторы, как правило, протягивают только проходящие функторы (контейнеры с конечным числом элементов), De протягивает все контейнеры. Так что это немного особенное. Интересно, что это такое.

и

Функтор De представляет фиксированную задержку, а не произвольную. Я делю время на отдельные кусочки. De x - это тип x, который должен быть на следующем слайсе. De (De x), таким образом, является типом x, подлежащим оплате за два среза, и вы не сможете заставить его подняться раньше!

Прочитайте весь пост. Чтобы ответить на ближайший вопрос, авторский вывод

Не смотри!

Хорошо, вот реализация. Это мошенничество.

newtype De x = De x deriving Show -- ssh, don't tell!

instance Functor De where
  fmap f (De x) = De (f x)

instance Applicative De where
  pure = De
  De f <*> De s = De (f s)

fix :: (De x -> x) -> x
fix f = f (De (fix f))
9 голосов
/ 24 января 2010

Недавно я определил экземпляр Applicative для нового типа поверх (,,,), «четырехугольника». (Стандартная библиотека определяет экземпляр для (,), но не (,,,). Это нормально, так как стандартная реализация имеет семантику, отличную от той, что была после.)

Фон есть; Я анализирую некоторые старые данные, и формат даты в данных неоднозначен. Каждую дату в данных можно разбить на четыре варианта, хранящихся в квадраторе. Затем я хочу проверить каждую дату в квадрате, чтобы исключить семантически неверные даты. (Нет месяцев с 32 днями, нет месяца 34, нет 5-го квартала и т. Д.) Наконец, я хочу взять каждую дату в наборе данных и сократить весь набор до четырех, представляющих, какие форматы дат действительны для всего набора. Затем я выбираю лучший формат из этих вариантов и предполагаю, что это формат даты набора данных.

Вся эта операция очень легко выразить как аппликативные операции над структурой квадрата.

Вот основная форма кода:

Мой новый тип:

newtype DQ a = DQ (a, a, a, a) -- date quad
             deriving ...

instance Functor DQ where
   g `fmap` f = pure g <*> f

instance Applicative DQ where
   pure x  = DQ (x, x, x, x)
   DQ (g, h, i, j) <*> DQ (a, b, c, d) = DQ (g a, h b, i c, j d)

Некоторые обязательные «чистые» функции:

parseDateInt :: Int -> DQ Date
validateDate :: Date -> Bool
extractBestDate :: DQ Date -> DQ Bool -> Date

Так что, как только у нас будет четверка проанализированных дат (от parseDateInt), нам нужно проверить их:

validateDates :: DQ Date -> DQ Bool
validateDates = (validateDate <$>)

(Пока это только Functor, но вы также можете написать (pure validateDate <*>).

Стоит также отметить симметрию между проверкой одного элемент, и проверка каждого элемента набора - чтобы проверить один, вы могли бы написать validateDate $ date; чтобы проверить набор, вы пишете validateDate <$> dates. Вот почему fmap записывается как <$>, это приложение функции к функтору.)

Шаг после этого состоит в том, чтобы взять набор допустимых разборов и сложить в окончательный результат:

intuitDateType :: [DQ Bool] -> DQ Bool
intuitDateType dates = foldl1 (liftA2 (&&)) dates

Так что теперь вы можете перейти от [Int] в файле данных к DQ Bool представляющие, возможно, допустимые представления даты для набора данных. (И оттуда, связать каждую точку данных с объектом реальной даты, вместо шелушащегося Int, который был поставлен.)

Так или иначе, этот пост стал немного длиннее, но идея в том, что Аппликативный пример позволил мне решить мою проблему примерно в 3 строки кода. Моя проблемная область неоднократно применяла функции к данным в контейнер, который делает аппликативный функтор. Для этих данных нет операции join, поэтому экземпляр Monad не имеет особого смысла.

5 голосов
/ 23 января 2010

Конал Эллиотт пишет о сигнальных процессорах и о том, как они применяются . Они похожи на ZipList по своей природе, где каждая соответствующая пара предметов в двух «контейнерах» объединяется.

Я часто использовал эту концепцию в незаконченной, но милой игре, которую я сделал (cabal install DefendTheKing, чтобы проверить это).

Фрагмент кода / пример использования в стиле Applicative:

draw font
<$> lstP gABoard
<*> lstP gASelection
<*> mouseMotion
<*> lstP gASide
<*> lstP gAGameIteration
4 голосов
/ 27 февраля 2012

Swierstra и Duponcheel определили эффективный стиль парсера, этот парсер был в значительной степени ранним потомком для Arrows, но ему не нужно ничего от Arrow, чего он не может получить от Applicative. Тем не менее, Аппликативные средства не были придуманы в то время.

Эффективно он вычисляет «ПЕРВЫЕ» наборы для синтаксического анализатора LL (1) и использует его для более разумного выбора ветви. Тем не менее, вы не можете вычислить эти наборы, когда вы работаете монадически.

Возможно, это не очень справедливый пример, потому что синтаксический анализатор Swierstra / Duponcheel допускает смешивание статических и динамических синтаксических анализаторов, и только статический анализатор ограничен быть аппликативным.

Благодаря наблюдаемому совместному использованию вы можете продвигать их дизайн парсера дальше, а также вычислять наборы «СЛЕДУЮЩИЙ» (если вы осторожны, чтобы не создавать бесконечную контекстно-свободную грамматику). Это дает хорошие асимптотические гарантии для синтаксического анализа не зависящих от контекста грамматик, которые недоступны вам при анализе с использованием монадных (контекстно-зависимых) конструкций синтаксического анализатора.

Также интересно, пожалуй, рассмотреть структуры, для которых доступно <*> аппликативного, но не чистого. Многие комонады допускают (<*>) -подобное определение, которое учитывает структуру комонады, но не имеет разумного определения «чистый». Мой пакет полугрупоидов и множество пакетов, которые зависят от него, исследуют эту идею дальше.

4 голосов
/ 07 декабря 2010

Formlets - это абстракция над формами HTML, описанная в терминах составления аппликативов. Аппликатив формы - это результат компоновки аппликата, генерирующего имя (для генерации имен элементов формы), аппликатив писателя XML (для генерации HTML) и аппликатив среды (для предоставления переданных значений формы).

Формулы могут быть расширены путем составления дополнительных аппликативов, например, для реализации проверки.

Купер, Вадлер и др. Показывают в работах, что форматы не могут быть представлены в виде монад.

В Haskell реализованы формулы, - это пакет .

1 голос
/ 27 февраля 2012

Макбрайд и Патерсон http://www.soi.city.ac.uk/~ross/papers/Applicative.pdf показывают, что моноид можно рассматривать как аппликативный функтор, но в общем случае это не монада.

1 голос
/ 23 января 2010

Я считаю, что стрелки являются аппликативными функторами. В Control.Applicative определенно есть тип WrapArrow.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...