Аппликативные функции, отличные от монадов и ZipList?
Двумя хорошо известными примерами аппликаций являются монады и ziplists. Есть ли другие примеры?
Ответы
Ответ 1
Из Время летает, как аппликативный функтор, Конор Макбрайд:
Структурные менты заметят, что De
- это еще один пример аппликативного функтора, который не является монадом - объединение принесет вещи из далекого будущего в ближайшем будущем, и это было бы лучше не возможно. Однако, когда аппликативные функторы вообще тянут через проходящие функции (контейнеры с конечным числом элементов), De
проталкивает все контейнеры. Так что это немного особенное. Интересно, что это такое.
и
Функтор De
представляет собой фиксированную задержку, а не произвольную. Im делит время на дискретные срезы. 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))
Ответ 2
Недавно я определил аппликативный экземпляр для newtype поверх (,,,)
, "quad". (Стандартная библиотека определяет экземпляр для (,)
, но не (,,,)
. Это нормально, поскольку стандартная реализация имеет разную семантику, чем то, что было после.)
Фон - это; Я разбираю некоторые старые данные, а формат даты в данных неоднозначен. Каждая дата в данных может быть проанализирована на четыре возможности, сохраненные в квадранте. Затем я хочу проверить каждую дату в квадрате, чтобы исключить семантически недействительные даты. (Нет месяцев с 32 днями, нет месяца 34, нет пятого квартала и т.д.). Наконец, я хочу взять каждую дату в наборе данных и уменьшить весь набор до квадрата, представляющего, какие форматы даты действительны для всего набора. Затем я выбираю лучший формат из этих параметров и предполагаю, что формат даты набора данных.
Вся эта операция очень легко выразить как прикладные операции на квадрантной структуре.
Здесь основная форма кода:
Мой новый тип:
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
представляющие возможные допустимые представления даты для набора данных.
(И оттуда свяжите каждую точку данных с реальным объектом даты,
а не flaky Int, который был поставлен.)
Так или иначе, этот пост получил немного длинный, но идея в том, что
Аппликационный пример позволил мне решить мою проблему примерно в 3 строках
кода. Мой проблемный домен неоднократно применял функции к данным в
контейнер, что и делает прикладной функтор. Для этих данных нет операции join
, поэтому экземпляр Monad не имеет большого смысла.
Ответ 3
Конал Эллиотт пишет о сигнальных процессорах и о том, как они применяются. Они похожи на ZipList
в природе, где каждая соответствующая пара элементов в двух "контейнерах" объединяется.
Я много использовал эту концепцию в незавершенной, но милой игре, которую я сделал (cabal install DefendTheKing
, чтобы проверить это).
Фрагмент кода/пример использования аппликативного стиля:
draw font
<$> lstP gABoard
<*> lstP gASelection
<*> mouseMotion
<*> lstP gASide
<*> lstP gAGameIteration
Ответ 4
Formlets являются абстракцией над формами HTML, описанными в терминах составления аппликаций. Аппликация формлета является результатом составления имени, генерирующего аппликативный (для генерации имен элементов формы), приложения для создания XML-кода (для генерации HTML) и применения среды (для подачи представленных значений формы).
Формлеты могут быть расширены за счет добавления дополнительных аппликаций, например для реализации проверки.
Купер, Вадлер и др. показывают в работах, что формылеты не могут быть представлены как монады.
В Haskell реализованы Formlets, вот пакет.
Ответ 5
Swierstra и Duponcheel определили эффективный стиль парсера, этот синтаксический анализатор был в значительной степени ранним платиновым ребенком для Arrows, но ему ничего не нужно от Arrow, которое он не может получить от Applicative. Тем не менее, в то время не было приложено применение.
Эффективно он вычисляет множества "FIRST" для парсера LL (1) и использует это для более интеллектуального выбора ветки. Тем не менее, вы не можете вычислять эти наборы, когда вы работаете монадически.
Это, пожалуй, не очень правдоподобный пример, потому что парсер Swierstra/Duponcheel допускает смешивание статических и динамических парсеров, и только статический парсер ограничивается возможностью применения.
С наблюдаемым разделением вы можете нести свой парсерный дизайн дальше, а также вычислить множества "FOLLOW" (пока вы не станете строить бесконечную контекстную грамматику). Это дает хорошие асимптотические гарантии для разбора контекстных свободных грамматик, которые недоступны вам при разборе с использованием монадических (контекстно-зависимых) парсеров.
Также интересным, возможно, является рассмотрение структур, для которых доступно аппликативное приложение, но не чистое. Многие comonads допускают (< * > ) -подобное определение, которое учитывает структуру comonad, но не имеют разумного определения для "чистого". Мой пакет semigroupoids и множество пакетов, которые зависят от него, исследуют эту идею дальше.
Ответ 6
Я считаю, что стрелы являются аппликативными функторами. В Control.Applicative есть тип WrapArrow.
Ответ 7
McBride и Paterson http://www.soi.city.ac.uk/~ross/papers/Applicative.pdf показывают, что моноид можно рассматривать как прикладной функтор, но в общем случае это не монада.