Я слышал термин «коалгебры» несколько раз в функциональном программировании и кругах PLT, особенно когда речь идет об объектах, комонадах, линзах и тому подобном. Погуглив этот термин, вы найдёте страницы, которые дают математическое описание этих структур, что для меня довольно непостижимо. Может ли кто-нибудь объяснить, что означают коалгебры в контексте программирования, каково их значение и как они связаны с объектами и комонадами?
scala
haskell
functional-programming
category-theory
recursion-schemes
missingfaktor
источник
источник
Ответы:
Алгебры
Я думаю, что для начала нужно понять идею алгебры . Это просто обобщение алгебраических структур, таких как группы, кольца, моноиды и так далее. В большинстве случаев эти вещи представлены в терминах наборов, но поскольку мы среди друзей, я расскажу о типах Haskell. (Я не могу удержаться от использования некоторых греческих букв - они заставляют все выглядеть круче!)
Таким образом, алгебра - это просто тип
τ
с некоторыми функциями и тождествами. Эти функции принимают различное количество аргументов типаτ
и выдаютτ
: uncurried, все они выглядят так(τ, τ,…, τ) → τ
. Они также могут иметь «идентичности» - элементы,τ
которые имеют специальное поведение с некоторыми функциями.Простейшим примером этого является моноид. Моноид - это любой тип
τ
с функциейmappend ∷ (τ, τ) → τ
и индивидуальностьюmzero ∷ τ
. Другие примеры включают в себя такие вещи, как группы (которые похожи на моноиды, за исключением дополнительнойinvert ∷ τ → τ
функции), кольца, решетки и так далее.Все функции работают,
τ
но могут иметь разные арности. Мы можем записать их какτⁿ → τ
, гдеτⁿ
карты для кортежаn
τ
. Таким образом, имеет смысл думать о самобытности ,τ⁰ → τ
гдеτ⁰
это только пустой кортеж()
. Так что теперь мы можем упростить идею алгебры: это просто некоторый тип с некоторым количеством функций.Алгебра - это просто общий паттерн в математике, который «вычеркнут», как мы делаем с кодом. Люди заметили, что целая куча интересных вещей - вышеупомянутые моноиды, группы, решетки и т. Д. - все следуют схожему шаблону, поэтому они абстрагировали его. Преимущество выполнения такого же, как в программировании: оно создает многократно используемые доказательства и облегчает определенные виды рассуждений.
F-алгебры
Тем не менее, мы не совсем закончили с факторингом. Пока у нас есть куча функций
τⁿ → τ
. Мы действительно можем сделать хитрый трюк, чтобы объединить их все в одну функцию. В частности, давайте посмотрим на моноиды: у нас естьmappend ∷ (τ, τ) → τ
иmempty ∷ () → τ
. Мы можем превратить их в одну функцию, используя тип суммыEither
. Это будет выглядеть так:Фактически мы можем использовать это преобразование несколько раз , чтобы объединить все те
τⁿ → τ
функции в один, для любой алгебры. (На самом деле, мы можем сделать это для любого числа функцийa → τ
,b → τ
и так далее для любогоa, b,…
.)Это позволяет нам говорить об алгебрах как о типе
τ
с единственной функцией от некоторого беспорядкаEither
s до единственногоτ
. Для моноидов, этот беспорядок:Either (τ, τ) ()
; для групп (которые имеют дополнительнуюτ → τ
операцию), это:Either (Either (τ, τ) τ) ()
. Это разные типы для каждой другой структуры. Так что же общего у всех этих типов? Наиболее очевидным является то, что все они являются просто суммами продуктов - алгебраическими типами данных. Например, для моноидов мы могли бы создать тип аргумента моноида, который работает для любого моноида τ:Мы можем сделать то же самое для групп, колец, решеток и всех других возможных структур.
Что еще особенного во всех этих типах? Ну, они все
Functors
! Например:Таким образом, мы можем обобщить нашу идею алгебры еще больше. Это просто какой-то тип
τ
с функциейf τ → τ
для некоторого функтораf
. Фактически, мы могли бы записать это как класс типов:Это часто называют "F-алгеброй", потому что это определяется функтором
F
. Если бы мы могли частично применить классы типов, мы могли бы определить что-то вродеclass Monoid = Algebra MonoidArgument
.коалгебрах
Теперь, надеюсь, вы хорошо понимаете, что такое алгебра и как это просто обобщение нормальных алгебраических структур. Так что же такое F-коалгебра? Ну, co подразумевает, что это «двойник» алгебры, то есть мы берем алгебру и переворачиваем стрелки. Я вижу только одну стрелку в приведенном выше определении, поэтому я просто переверну это:
И это все, что есть! Теперь этот вывод может показаться немного легкомысленным (хе). Он говорит вам, что такое коалгебра, но на самом деле не дает никакого представления о том, как это полезно или почему мы заботимся. Я вернусь к этому чуть позже, когда найду или придумаю хороший пример или два: P.
Классы и Объекты
Прочитав немного, я думаю, у меня есть хорошая идея о том, как использовать коалгебры для представления классов и объектов. У нас есть тип,
C
который содержит все возможные внутренние состояния объектов в классе; сам класс представляет собой коалгебру, надC
которой определяются методы и свойства объектов.Как показано в примере алгебры, если у нас есть набор функций, подобных
a → τ
иb → τ
для любойa, b,…
, мы можем объединить их все в одну функцию, используяEither
тип суммы. Двойное «понятие» была бы объединение кучи функций типаτ → a
,τ → b
и так далее. Мы можем сделать это, используя двойственный тип суммы - тип продукта. Итак, учитывая две функции выше (они называютсяf
иg
), мы можем создать одну такую:Тип
(a, a)
является функтором в прямом смысле, поэтому он, безусловно, согласуется с нашим понятием F-коалгебры. Этот конкретный трюк позволяет нам упаковать множество различных функций - или, для ООП, методов - в одну функцию типаτ → f τ
.Элементы нашего типа
C
представляют внутреннее состояние объекта. Если объект обладает некоторыми читаемыми свойствами, он должен иметь возможность зависеть от состояния. Самый очевидный способ сделать это - сделать их функциейC
. Поэтому, если мы хотим иметь свойство длины (напримерobject.length
), у нас будет функцияC → Int
.Нам нужны методы, которые могут принимать аргумент и изменять состояние. Для этого нам нужно взять все аргументы и выдать новое
C
. Давайте представимsetPosition
метод , который принимаетx
иy
координатуobject.setPosition(1, 2)
. Это будет выглядеть следующим образом :C → ((Int, Int) → C)
.Важным примером здесь является то, что «методы» и «свойства» объекта принимают сам объект в качестве первого аргумента. Это так же, как
self
параметр в Python и как неявныйthis
во многих других языках. Коалгебра по существу только инкапсулирует поведение принимаетself
параметр: это то , что первыйC
вC → F C
это.Итак, давайте соберем все это вместе. Давайте представим класс со
position
свойством,name
свойством иsetPosition
функцией:Нам нужно две части, чтобы представить этот класс. Во-первых, нам нужно представить внутреннее состояние объекта; в этом случае он просто содержит два
Int
s и aString
. (Это наш типC
.) Затем нам нужно придумать коалгебру, представляющую класс.У нас есть два свойства для записи. Они довольно тривиальны
Теперь нам нужно только обновить позицию:
Это так же, как класс Python с его явными
self
переменными. Теперь, когда у нас есть наборself →
функций, нам нужно объединить их в одну функцию для коалгебры. Мы можем сделать это с помощью простого кортежа:Тип
((Int, Int), String, (Int, Int) → c)
-для любойc
-является функтор, поэтомуcoop
имеет форму мы хотим:Functor f ⇒ C → f C
.Учитывая это,
C
наряду сcoop
формой коалгебры, которая определяет класс, который я дал выше. Вы можете увидеть, как мы можем использовать эту же технику, чтобы указать любое количество методов и свойств для наших объектов.Это позволяет нам использовать коалгебраические рассуждения для работы с классами. Например, мы можем ввести понятие «гомоморфизма F-коалгебры» для представления преобразований между классами. Это страшно звучащий термин, который просто означает преобразование между коалгебрами, которое сохраняет структуру. Это позволяет намного легче думать о отображении классов на другие классы.
Короче говоря, F-коалгебра представляет класс, имея набор свойств и методов, которые все зависят от
self
параметра, содержащего внутреннее состояние каждого объекта.Другие категории
До сих пор мы говорили об алгебрах и коалгебрах как о типах Хаскеля. Алгебра - это просто тип
τ
с функцией,f τ → τ
а коалгебра - это просто типτ
с функциейτ → f τ
.Однако ничто не связывает эти идеи с Хаскеллом как таковым . Фактически, они обычно вводятся в терминах множеств и математических функций, а не типов и функций Haskell. Действительно, мы можем обобщить эти понятия на любые категории!
Мы можем определить F-алгебру для некоторой категории
C
. Во-первых, нам нужен функтор,F : C → C
то есть эндофунктор . (Все HaskellFunctor
s фактически endofunctors отHask → Hask
.) Тогда алгебра только объектA
изC
с морфизмаF A → A
. Коалгебра такая же, как сA → F A
.Что мы получаем, рассматривая другие категории? Ну, мы можем использовать одни и те же идеи в разных контекстах. Как монады. В Хаскеле монада - это некий тип
M ∷ ★ → ★
с тремя операциями:map
Функция просто является доказательством того , чтоM
являетсяFunctor
. Таким образом, мы можем сказать, что монада - это просто функтор с двумя операциями:return
иjoin
.Функторы сами образуют категорию, причем морфизмы между ними являются так называемыми «естественными преобразованиями». Естественное преобразование - это просто способ преобразовать один функтор в другой, сохранив при этом его структуру. Вот хорошая статья, помогающая объяснить идею. Это говорит о том
concat
, что толькоjoin
для списков.С функторами Haskell композиция двух функторов сама является функтором. В псевдокоде мы могли бы написать это:
Это помогает нам думать
join
как отображениеf ∘ f → f
. Типjoin
есть∀α. f (f α) → f α
. Интуитивно понятно, что можно рассматривать функцию, действительную для всех типов,α
как преобразованиеf
.return
аналогичная трансформация. Его тип есть∀α. α → f α
. Это выглядит по-другому - первоеα
не «в» функторе! К счастью, мы можем это исправить, добавив тождественный функтор есть:∀α. Identity α → f α
. Какreturn
и трансформацияIdentity → f
.Теперь мы можем думать о монаде как о алгебре, основанной на некотором функторе
f
с операциямиf ∘ f → f
иIdentity → f
. Разве это не выглядит знакомым? Это очень похоже на моноид, который был просто каким-то типомτ
с операциямиτ × τ → τ
и() → τ
.Таким образом, монада похожа на моноид, за исключением того, что вместо типа у нас есть функтор. Это такая же алгебра, просто в другой категории. (Вот откуда фраза «монада - это просто моноид в категории эндофункторов», насколько я знаю.)
Теперь у нас есть эти две операции:
f ∘ f → f
иIdentity → f
. Чтобы получить соответствующую коалгебру, мы просто щелкаем стрелками. Это дает нам две новые операции:f → f ∘ f
иf → Identity
. Мы можем превратить их в типы Haskell, добавив переменные типа, как указано выше, предоставив нам∀α. f α → f (f α)
и∀α. f α → α
. Это выглядит так же, как определение комонады:Таким образом, комонада является коалгеброй в категории эндофункторов.
источник
(,)
функтору идентичности()
. Моноидный объект в моноидальной категории - это объект со стрелками, соответствующими вашей моноидной алгебре, который описывает моноидный объект в Hask с типами продуктов в качестве моноидальной структуры. Моноидный объект в категории эндофункторов на C - это монада на C, так что да, ваше понимание верно. :]F-алгебры и F-коалгебры - это математические структуры, которые помогают рассуждать об индуктивных типах (или рекурсивных типах ).
F-алгебра
Начнем сначала с F-алгебр. Я постараюсь быть максимально простым.
Я думаю, вы знаете, что такое рекурсивный тип. Например, это тип для списка целых чисел:
Очевидно, что он рекурсивный - действительно, его определение относится к самому себе. Его определение состоит из двух конструкторов данных, которые имеют следующие типы:
Обратите внимание, что я написал тип
Nil
как() -> IntList
, а не простоIntList
. Это фактически эквивалентные типы с теоретической точки зрения, потому что у()
типа есть только один обитатель.Если мы напишем сигнатуры этих функций более теоретическим способом, мы получим
где
1
- единичный набор (набор из одного элемента), аA × B
операция - это перекрестное произведение двух наборовA
иB
(то есть набор пар,(a, b)
гдеa
проходит через все элементыA
иb
проходит через все элементыB
).Несвязное объединение двух множеств
A
иB
является множеством,A | B
которое является объединением множеств{(a, 1) : a in A}
и{(b, 2) : b in B}
. По сути , это совокупность всех элементов из обоихA
иB
, но с каждым из этих элементов «помеченных» как принадлежащие либоA
илиB
, так что, когда мы выбираем любой элемент изA | B
нас будет знать немедленно пришел ли этот элемент изA
или изB
.Мы можем «объединять»
Nil
иCons
функции, чтобы они образовывали одну функцию, работающую над множеством1 | (Int × IntList)
:Действительно, если
Nil|Cons
функция применяется к()
значению (которое, очевидно, принадлежит1 | (Int × IntList)
множеству), то оно ведет себя так, как если бы оно былоNil
; ЕслиNil|Cons
применяется к любому значению типа(Int, IntList)
(такие значения также есть в наборе1 | (Int × IntList)
, он ведет себя какCons
.Теперь рассмотрим другой тип данных:
Имеет следующие конструкторы:
который также может быть объединен в одну функцию:
Видно, что обе эти
joined
функции имеют сходный тип: они обе выглядят какгде
F
это своего рода преобразование , которое принимает наш тип и дает более сложный тип, который состоит изx
и|
операции, обычаиT
и , возможно , другие типы. Например, дляIntList
иIntTree
F
выглядит следующим образом:Мы можем сразу заметить, что любой алгебраический тип может быть записан таким образом. Действительно, именно поэтому они называются «алгебраическими»: они состоят из ряда «сумм» (союзов) и «произведений» (перекрестных произведений) других типов.
Теперь мы можем определить F-алгебру. F-алгебра - это просто пара
(T, f)
, гдеT
некоторый тип иf
функция типаf :: F T -> T
. В наших примерах F-алгебрами являются(IntList, Nil|Cons)
и(IntTree, Leaf|Branch)
. Обратите внимание, однако, что, несмотря на то, что типf
функции одинаков для каждого F,T
иf
сами могут быть произвольными. Например,(String, g :: 1 | (Int x String) -> String)
или(Double, h :: Int | (Double, Double) -> Double)
для некоторых,g
аh
также являются F-алгебрами для соответствующих F.После этого мы можем ввести гомоморфизмы F-алгебры, а затем начальные F-алгебры , которые обладают очень полезными свойствами. Фактически,
(IntList, Nil|Cons)
является начальной F1-алгеброй и(IntTree, Leaf|Branch)
является начальной F2-алгеброй. Я не буду представлять точные определения этих терминов и свойств, поскольку они более сложны и абстрактны, чем необходимо.Тем не менее тот факт, что, скажем,
(IntList, Nil|Cons)
является F-алгеброй, позволяет нам определятьfold
подобную функцию для этого типа. Как вы знаете, сложение - это своего рода операция, которая преобразует некоторый рекурсивный тип данных в одно конечное значение. Например, мы можем сложить список целых чисел в одно значение, которое является суммой всех элементов в списке:Такая операция может быть обобщена для любого рекурсивного типа данных.
Ниже приведена подпись
foldr
функции:Обратите внимание, что я использовал фигурные скобки для отделения первых двух аргументов от последнего. Это не настоящая
foldr
функция, но она изоморфна ей (то есть вы легко можете получить одно из другого и наоборот). Частично применяетсяfoldr
будет иметь следующую подпись:Мы можем видеть, что это функция, которая принимает список целых чисел и возвращает одно целое число. Давайте определим такую функцию в терминах нашего
IntList
типа.Мы видим, что эта функция состоит из двух частей: первая часть определяет поведение этой функции на
Nil
частиIntList
, а вторая часть определяет поведение функции наCons
части.Теперь предположим, что мы программируем не на Haskell, а на каком-то языке, который позволяет использовать алгебраические типы непосредственно в сигнатурах типов (ну, технически Haskell позволяет использовать алгебраические типы через кортежи и
Either a b
типы данных, но это приведет к ненужному многословию). Рассмотрим функцию:Видно, что
reductor
это функция типаF1 Int -> Int
, как в определении F-алгебры! Действительно, пара(Int, reductor)
является F1-алгеброй.Поскольку
IntList
является начальным F1-алгебра, для каждого типа ,T
и для каждой функцииr :: F1 T -> T
существует функции, называемый катаморфизмом дляr
, который преобразуетIntList
доT
, и такая функция является уникальной. Действительно, в нашем примере катаморфизм дляreductor
issumFold
. Обратите внимание, какreductor
иsumFold
схожи: они имеют почти одинаковую структуру! Вreductor
определении определенияs
использование (тип которого соответствуетT
) соответствует использованию результата вычисленияsumFold xs
вsumFold
определении.Просто чтобы сделать его более понятным и помочь вам увидеть шаблон, вот еще один пример, и мы снова начнем с полученной функции свертывания. Рассмотрим
append
функцию, которая добавляет свой первый аргумент ко второму:Вот как это выглядит на нашем
IntList
:Опять же, давайте попробуем выписать редуктор:
appendFold
это катаморфизм, дляappendReductor
которого превращаетсяIntList
вIntList
.Таким образом, по существу, F-алгебры позволяют нам определять «складки» на рекурсивных структурах данных, то есть операции, которые приводят наши структуры к некоторому значению.
F-коалгебрами
F-коалгебры - это так называемый «двойственный» термин для F-алгебр. Они позволяют нам определить
unfolds
для рекурсивных типов данных, то есть способ построить рекурсивные структуры из некоторого значения.Предположим, у вас есть следующий тип:
Это бесконечный поток целых чисел. Его единственный конструктор имеет следующий тип:
Или, с точки зрения наборов
Haskell позволяет вам сопоставлять шаблоны с конструкторами данных, поэтому вы можете определить следующие функции, работающие с
IntStream
s:Вы можете естественным образом «объединить» эти функции в одну функцию типа
IntStream -> Int × IntStream
:Обратите внимание, что результат функции совпадает с алгебраическим представлением нашего
IntStream
типа. То же самое можно сделать и для других рекурсивных типов данных. Может быть, вы уже заметили шаблон. Я имею в виду семейство функций типагде
T
какой-то тип. С этого момента мы будем определятьТеперь F-коалгебра - это пара
(T, g)
, гдеT
есть тип иg
функция типаg :: T -> F T
. Например,(IntStream, head&tail)
это F1-коалгебра. Опять же, как и в F-алгебрах,g
иT
может быть произвольным, например,(String, h :: String -> Int x String)
также является F1-коалгеброй для некоторого h.Среди всех F-коалгебр есть так называемые терминальные F-коалгебры , двойственные к исходным F-алгебрам. Например,
IntStream
является терминальной F-коалгеброй. Это означает, что для каждого типаT
и для каждой функцииp :: T -> F1 T
существует функция, называемая анаморфизмом , которая преобразуетсяT
вIntStream
, и такая функция уникальна.Рассмотрим следующую функцию, которая генерирует поток последовательных целых чисел, начиная с заданной:
Теперь давайте проверим функцию
natsBuilder :: Int -> F1 Int
, то естьnatsBuilder :: Int -> Int × Int
:Опять же, мы можем увидеть некоторое сходство между
nats
иnatsBuilder
. Это очень похоже на связь, которую мы наблюдали с редукторами и сгибами ранее.nats
это анаморфизм дляnatsBuilder
.Другой пример: функция, которая принимает значение и функцию и возвращает поток последовательных применений функции к значению:
Его строительная функция следующая:
Тогда
iterate
анаморфизм дляiterateBuilder
.Вывод
Итак, короче говоря, F-алгебры позволяют определять складки, то есть операции, которые сводят рекурсивную структуру до единого значения, а F-коалгебры позволяют делать обратное: построить [потенциально] бесконечную структуру из одного значения.
Фактически в Хаскелле F-алгебры и F-коалгебры совпадают. Это очень приятное свойство, которое является следствием наличия значения «bottom» в каждом типе. Таким образом, в Haskell могут быть созданы как сгибы, так и сгибы для каждого рекурсивного типа. Однако теоретическая модель, стоящая за этим, является более сложной, чем та, которую я представил выше, поэтому я намеренно избегал ее.
Надеюсь это поможет.
источник
appendReductor
выглядит немного странно и не очень помогли мне увидеть шаблон там ... :) Можете ли вы еще раз проверить, что он правильный? .. Как должны выглядеть типы редукторов в целом? В определенииr
тамF1
определяется IntList или это произвольный F?Просмотр учебного пособия Учебник по (со) алгебрам и (со) индукции должен дать вам некоторое представление о коалгебре в информатике.
Ниже приводится цитата, чтобы убедить вас,
Прелюдия, о теории категорий. Теория категорий должна быть переименована в теорию функторов. Поскольку категории - это то, что нужно определить, чтобы определить функторы. (Более того, функторы - это то, что нужно определить, чтобы определить естественные преобразования.)
Что за функтор? Это преобразование из одного набора в другой, сохраняющее их структуру. (Для более подробной информации есть много хорошего описания в сети).
Что такое F-алгебра? Это алгебра функтора. Это всего лишь изучение универсальной уместности функтора.
Как это может быть ссылка на информатику? Программу можно рассматривать как структурированный набор информации. Выполнение программы соответствует модификации этого структурированного набора информации. Звучит хорошо, что выполнение должно сохранить структуру программы. Тогда выполнение можно рассматривать как приложение функтора над этим набором информации. (Тот, который определяет программу).
Почему F-коалгебра? Программы двойственны по своей сути, так как они описываются информацией и действуют на нее. Тогда в основном информацию, составляющую программу и изменяющую их, можно просматривать двояко.
Тогда на этом этапе я бы хотел сказать,
В течение жизни программы данные и состояние сосуществуют, и они дополняют друг друга. Они двойственны.
источник
Я начну с материалов, которые, очевидно, связаны с программированием, а затем добавлю некоторые математические материалы, чтобы они были как можно более конкретными и практичными.
Давайте процитируем некоторых компьютерных ученых по коиндукции ...
http://www.cs.umd.edu/~micinski/posts/2012-09-04-on-understanding-coinduction.html
http://adam.chlipala.net/cpdt/html/Coinductive.html
http://www.alexandrasilva.org/#/talks.html
Отношение окружающего математического контекста к обычным задачам программирования
Что такое "алгебра"?
Алгебраические структуры обычно выглядят так:
Это должно звучать как объекты с 1. свойствами и 2. методами. Или даже лучше, это должно звучать как подписи типа.
Стандартные математические примеры включают моноид ⊃ группа-вектор-пространство ⊃ «алгебра». Моноиды похожи на автоматы: последовательности глаголов (например,
f.g.h.h.nothing.f.g.f
).git
Журнал , который всегда добавляет истории и никогда не удаляет это будет Моноид , но не группа. Если вы добавите обратное (например, отрицательные числа, дроби, корни, удаление накопленной истории, не разбив разбитое зеркало), вы получите группу.Группы содержат вещи, которые могут быть добавлены или вычтены вместе. Например,
Duration
s могут быть добавлены вместе. (НоDate
s не может.) Длительности живут в векторном пространстве (не только в группе), потому что они также могут быть масштабированы по внешним числам. (Тип подписиscaling :: (Number,Duration) → Duration
.)Алгебры ⊂ вектор-пространства могут сделать еще одну вещь: есть некоторые
m :: (T,T) → T
. Назовите это «умножение» или не делайте, потому что, как только вы уйдете,Integers
становится менее очевидно, каким должно быть «умножение» (или «возведение в степень» ).(Вот почему люди обращаются к категории (теоретико-) универсальным свойствам: сказать им , что умножение должно делать или быть , как :
)
Алгебры → коалгебры
Комультиплицирование легче определить таким образом, который кажется не произвольным, чем умножение, потому что для перехода от
T → (T,T)
него можно просто повторить один и тот же элемент. («Диагональное отображение» - как диагональные матрицы / операторы в спектральной теории)Счет - это обычно след (сумма диагональных входов), хотя, опять же, важно то, что делает ваш счет ;
trace
это просто хороший ответ для матриц.В общем, причина взглянуть на двойственное пространство состоит в том, что в этом пространстве легче мыслить. Например, иногда проще думать о нормальном векторе, чем о плоскости, к которой он нормален, но вы можете управлять плоскостями (включая гиперплоскости) с помощью векторов (и теперь я говорю о знакомом геометрическом векторе, как в трассировщике лучей) ,
Укрощение (не) структурированных данных
Математики могут моделировать что-то забавное, как TQFT , в то время как программисты должны бороться с
+ :: (Date,Duration) → Date
),Paris
≠(+48.8567,+2.3508)
! Это форма, а не точка.),Информатики, говоря о коалгебрах, обычно имеют в виду операции с сеткой, как декартово произведение. Я считаю, что именно это имеют в виду люди, когда говорят: «Алгебры - это коалгебры в Хаскеле» Но в той степени, в которой программистам приходится моделировать сложные типы данных, такие как
Place
,Date/Time
иCustomer
- и делать эти модели максимально похожими на реальный мир (или, по крайней мере, на взгляд конечного пользователя на реальный мир) - я считаю, может быть полезным за пределами только сет-мира.источник