Я видел этот термин Free Монада всплывал каждый в настоящее время , и затем в течение некоторого времени, но каждый раз кажется , что использование / обсуждать их , не давая объяснение того , что они есть. Итак: что такое бесплатные монады? (Я бы сказал, что я знаком с монадами и основами Хаскелла, но имею только очень грубые знания теории категорий.)
haskell
monads
free-monad
Дэвид
источник
источник
Ответы:
Ответ Эдварда Кметта, очевидно, великолепен. Но это немного технический. Вот, пожалуй, более доступное объяснение.
Свободные монады - это просто общий способ превращения функторов в монады. То есть, учитывая, что любой функтор
f
Free f
является монадой. Это было бы не очень полезно, если бы вы не получили пару функцийпервый из них позволяет вам «войти» в вашу монаду, а второй - как «выйти» из нее.
В более общем смысле, если X - это Y с некоторыми дополнительными элементами P, то «свободный X» - это способ перехода от Y к X без получения чего-либо дополнительного.
Примеры: моноид (X) - это набор (Y) с дополнительной структурой (P), который в основном говорит, что у него есть операция (вы можете думать о сложении) и некоторая идентичность (например, ноль).
Так
Теперь мы все знаем списки
Ну, учитывая любой тип,
t
мы знаем, что[t]
это моноиди поэтому списки являются «свободным моноидом» над наборами (или в типах Haskell).
Итак, бесплатные монады - это та же идея. Мы берем функтор и возвращаем монаду. Фактически, поскольку монады можно рассматривать как моноиды в категории эндофункторов, определение списка
очень похоже на определение свободных монад
и
Monad
экземпляр имеет сходство сMonoid
экземпляром для списковтеперь мы получаем две наши операции
источник
Free f a = Pure a | Roll (f (Free f a))
какFree f a = a + fa + ffa + ...
, например, «F применяется к любое количество раз». ЗатемconcatFree
(то естьjoin
) принимает «f применено любое количество раз к (f применено любое количество раз к a)» и объединяет два вложенных приложения в одно. И>>=
принимает «f применено любое количество раз к a» и «как получить от a к (b с f применено любое количество раз)», и в основном применяет последнее к a внутри первого и разрушает вложение. Теперь я сама это понимаю!concatFree
принципеjoin
?Вот еще более простой ответ: Монада - это то, что «вычисляется», когда монадический контекст разрушается
join :: m (m a) -> m a
(напоминая, что>>=
это можно определить какx >>= y = join (fmap y x)
). Вот как монады переносят контекст через последовательную цепочку вычислений: потому что в каждой точке ряда контекст предыдущего вызова свернут со следующим.А свободная монада удовлетворяет все законы Монады, но не делают какое - либо рушится (то есть вычисление). Он просто создает вложенную серию контекстов. Пользователь, который создает такое бесплатное монадическое значение, отвечает за то, чтобы что-то делать с этими вложенными контекстами, так что значение такой композиции может быть отложено до тех пор, пока монадное значение не будет создано.
источник
Случайно, что бесплатный foo - это самая простая вещь, которая удовлетворяет всем законам «foo». То есть он полностью соответствует законам, необходимым для того, чтобы быть обманщиком, и ничего лишнего.
Забывчивый функтор - это тот, кто «забывает» часть структуры при переходе из одной категории в другую.
Данные функторы
F : D -> C
, иG : C -> D
, мы говоримF -| G
,F
присоединены слеваG
илиG
присоединены справа кF
всякий раз, когда все a, b:F a -> b
изоморфноa -> G b
, где стрелки приходят из соответствующих категорий.Формально свободный функтор оставляется присоединенным к забывчивому функтору.
Свободный моноид
Давайте начнем с более простого примера - свободного моноида.
Возьмите моноид, который определяется некоторым набором носителей
T
, бинарная функция помять пару элементов вместеf :: T → T → T
, иunit :: T
, таким образом, что у вас есть ассоциативный закон, и закон идентичности:f(unit,x) = x = f(x,unit)
.Вы можете сделать функтор
U
из категории моноидов (где стрелки являются моноидными гомоморфизмами, то есть они гарантируют, что они сопоставляютсяunit
сunit
другим моноидом, и что вы можете создавать до или после сопоставления с другим моноидом без изменения значения) в категорию наборов (где стрелки - просто функциональные стрелки), которые «забывают» об операции иunit
, и просто дают вам набор несущих.Затем вы можете определить функтор
F
из категории множеств обратно в категорию моноидов, оставленных присоединенными к этому функтору. Этот функтор является функтором, который отображает наборa
в моноид[a]
, гдеunit = []
иmappend = (++)
.Итак, чтобы рассмотреть наш пример до сих пор, в псевдо-Haskell:
Затем, чтобы показать, что
F
это бесплатно, мы должны продемонстрировать, что он оставлен присоединенным кU
забывчивому функтору, то есть, как мы упоминали выше, нам нужно показать, чтоF a → b
изоморфенa → U b
помните, что цель
F
находится в категорииMon
моноидов, где стрелки являются моноидными гомоморфизмами, поэтому нам нужно показать, что гомоидизм моноидов из[a] → b
может быть точно описан функцией изa → b
.В Haskell мы называем ту сторону этого, которая живет в
Set
(то есть,Hask
категория типов Haskell, которую мы притворяемся, это Set), простоfoldMap
, которая, когда специализируется отData.Foldable
Lists, имеет типMonoid m => (a → m) → [a] → m
.Из этого следствия вытекают последствия. Примечательно, что если вы забудете, то создайте бесплатно, а затем снова забудете, это так же, как вы однажды забыли, и мы можем использовать это для создания монадического соединения. так как
UFUF
~U(FUF)
~UF
, и мы можем перейти в тождестве моноидного гомоморфизма[a]
с[a]
помощью изоморфизма , который определяет наше примыкание, получаю , что список изоморфизмомом[a] → [a]
является функцией типаa -> [a]
, и это просто вернуться к спискам.Вы можете составить все это более непосредственно, описав список в следующих терминах:
Свободная Монада
Так что же такое свободная монада ?
Ну, мы делаем то же самое, что и раньше, мы начинаем с забывчивого функтора U из категории монад, где стрелки - гомоморфизмы монад, в категорию эндофункторов, где стрелки - естественные преобразования, и мы ищем функтор, который оставляется присоединенным. к тому, что.
Итак, как это относится к понятию свободной монады, как это обычно используется?
Знание того, что что-то является свободной монадой,
Free f
говорит вам, что дать гомоморфизм монады изFree f -> m
, это то же самое (изоморфно), что и дать естественное преобразование (гомоморфизм функторов) изf -> m
. Помните, что онF a -> b
должен быть изоморфным для того,a -> U b
чтобы F оставался присоединенным к U. Здесь монады отображаются на функторы.F, по крайней мере, изоморфен
Free
типу, который я использую в моемfree
пакете при взломе.Мы могли бы также построить его в более тесной аналогии с приведенным выше кодом для свободного списка, определив
Кофейные Комонады
Мы можем построить нечто подобное, взглянув на правое сопряжение с забывчивым функтором, предполагая, что оно существует. Свободный функтор просто / прямо присоединен / к забывчивому функтору, и симметрично знать, что что-то является свободной комонадой, - это то же самое, что знать, что давать гомоморфизм комонады из
w -> Cofree f
- это то же самое, что давать естественное преобразование изw -> f
.источник
Свободная монада (структура данных) относится к монаде (классу), как список (структура данных) к моноиду (классу): это тривиальная реализация, в которой вы можете впоследствии решить, как будет комбинироваться контент.
Вы , наверное , знаете , что такое Монада и что каждая Монада нуждается в конкретных (Monad-законопослушные) осуществление любой
fmap
+join
+return
илиbind
+return
.Предположим, у вас есть Functor (реализация
fmap
), но все остальное зависит от значений и выборов, сделанных во время выполнения, что означает, что вы хотите иметь возможность использовать свойства Monad, но затем хотите выбрать функции Monad.Это можно сделать с помощью Free Monad (структура данных), которая оборачивает Functor (тип) таким образом, что
join
это скорее сложение этих функторов, чем сокращение.Реальное
return
и котороеjoin
вы хотите использовать, теперь могут быть заданы в качестве параметров функции сокращенияfoldFree
:Чтобы объяснить типы, мы можем заменить
Functor f
наMonad m
иb
на(m a)
:источник
Свободная монада Haskell - это список функторов. Для сравнения:
Pure
аналогичноNil
иFree
аналогичноCons
. Бесплатная монада хранит список функторов вместо списка значений. Технически, вы можете реализовать бесплатные монады, используя другой тип данных, но любая реализация должна быть изоморфна вышеупомянутой.Вы используете бесплатные монады всякий раз, когда вам нужно абстрактное синтаксическое дерево. Базовый функтор свободной монады - это форма каждого шага синтаксического дерева.
Мой пост , который кто-то уже связал, дает несколько примеров того, как строить абстрактные синтаксические деревья со свободными монадами.
источник
Я думаю, что простой конкретный пример поможет. Предположим, у нас есть функтор
с очевидным
fmap
. ТогдаFree F a
тип деревьев, листья которых имеют типa
и чьи узлы помеченыOne
,Two
,Two'
иThree
.One
узлы -nodes имеют одного дочернего элемента,Two
аTwo'
узлы -no имеют двух дочернихThree
узлов, а узлы -no имеют три дочерних элемента и также помечаются знакомInt
.Free F
это монадаreturn
отображаетсяx
на дерево, которое является просто листом со значениемx
.t >>= f
смотрит на каждое из листьев и заменяет их деревьями. Когда лист имеет значение,y
он заменяет этот лист деревомf y
.Диаграмма делает это более понятным, но у меня нет возможности легко ее нарисовать!
источник