Я пришел из C #, где LINQ эволюционировал в Rx.NET, но всегда интересовался FP. После некоторого введения в монады и некоторых побочных проектов в F # я был готов попытаться перейти на следующий уровень.
Теперь, после нескольких разговоров о бесплатной монаде от людей из Scala и нескольких рецензий на Haskell или F #, я обнаружил, что грамматики с интерпретаторами для понимания очень похожи на IObservable
цепочки.
В FRP вы создаете определение операции из более мелких специфичных для домена кусков, включая побочные эффекты и сбои, которые остаются внутри цепочки, и моделируете свое приложение как набор операций и побочных эффектов. В свободной монаде, если я правильно понял, вы делаете то же самое, выполняя свои операции как функторы и поднимая их с помощью койонеды.
Каковы будут различия между обоими, которые наклоняют иглу к любому из подходов? В чем принципиальная разница при определении вашей услуги или программы?
источник
Cont
единственная монада, которую я видел, предполагала, что не может быть выражена через свободную монаду, можно предположить, что FRP может быть. Как и почти все остальное .IObservable
он является примером монады продолжения.Ответы:
Монады
Монада состоит из
Endofunctor . В нашем мире разработки программного обеспечения мы можем сказать, что это соответствует типу данных с одним параметром неограниченного типа. В C # это будет что-то вроде:
Две операции, определенные для этого типа данных:
return
/pure
принимает «чистое» значение (т. е.T
значение) и «оборачивает» его в монаду (т. е. производитM<T>
значение). Посколькуreturn
это зарезервированное ключевое слово в C #,pure
теперь я буду ссылаться на эту операцию. В C #pure
будет метод с подписью, как:bind
/flatmap
принимает монадическое значение (M<A>
) и функциюf
.f
принимает чистое значение и возвращает монадическое значение (M<B>
). Из нихbind
выдает новое монадическое значение (M<B>
).bind
имеет следующую подпись C #:Кроме того, чтобы быть монадой,
pure
иbind
обязаны соблюдать три монадических закона.Теперь одним из способов моделирования монад в C # было бы создание интерфейса:
(Примечание. Для краткости и выразительности я буду использовать некоторые возможности кода в этом ответе.)
Теперь мы можем реализовать монады для конкретных типов данных путем реализации конкретных реализаций
Monad<M>
. Например, мы могли бы реализовать следующую монаду дляIEnumerable
:(Я целенаправленно использую синтаксис LINQ, чтобы вызвать связь между синтаксисом LINQ и монадами. Но учтите, что мы могли бы заменить запрос LINQ вызовом
SelectMany
.)Теперь мы можем определить монаду для
IObservable
? Казалось бы, так:Чтобы убедиться, что у нас есть монада, нам нужно доказать законы монады. Это может быть нетривиально (и я не достаточно знаком с Rx.NET, чтобы знать, можно ли их доказать даже из одной спецификации), но это многообещающее начало. Чтобы облегчить оставшуюся часть этого обсуждения, давайте просто предположим, что в этом случае действуют законы монады.
Бесплатные монады
Не существует единственной «свободной монады». Скорее, свободные монады - это класс монад, которые построены из функторов. То есть, учитывая функтор
F
, мы можем автоматически получить монадуF
(то есть свободную монадуF
).ФУНКТОРЫ
Как и монады, функторы могут быть определены следующими тремя элементами:
Две операции:
pure
оборачивает чистое значение в функтор. Это аналогичноpure
для монады. Фактически, для функторов, которые также являются монадами, они должны быть идентичными.fmap
сопоставляет значения на входе с новыми значениями на выходе с помощью данной функции. Это подпись:Как и монады, функторы обязаны подчиняться законам функторов.
Подобно монадам, мы можем моделировать функторы через следующий интерфейс:
Теперь, поскольку монады являются подклассом функторов, мы могли бы также
Monad
немного изменить рефакторинг :Здесь я добавил дополнительный метод
join
и предоставил реализации по умолчанию для обоихjoin
иbind
. Обратите внимание, однако, что это круговые определения. Таким образом, вам придется переопределить хотя бы один или другой. Также обратите внимание, чтоpure
теперь наследуется отFunctor
.IObservable
и бесплатные монадыТеперь, поскольку мы определили монаду для
IObservable
и поскольку монады являются подклассом функторов, из этого следует, что мы должны быть в состоянии определить экземпляр функтора дляIObservable
. Вот одно определение:Теперь, когда у нас определен функтор
IObservable
, мы можем построить свободную монаду из этого функтора. И это именно то, какIObservable
относится к свободным монадам, а именно, из чего мы можем построить свободную монадуIObservable
.источник