и нужна возня со скрытием старой Group
Пусть будет открытой, это же ничему не помешает. То есть виды групп разводятся по именам. Если явно используется одно название, значит одна группа, если другое - другая. Всё очевидно любому, кто посмотрит текст такой программы. Увидит привычную стандартную группу - поймёт, что это такое. Увидит вашу - догадается из названия.
Не нарушает.
Вообще да, если плюсовать два разных типа - компилятор сругается. Но сама перегрузка использования одного обозначения для многих смыслов меня напрягает. Это как в математике - один использовал большие буквы для обозначения множеств, а другой для групп, при этом я читая первого что-то понимал, а перешёл на другого - перестал понимать. То есть всё в конце концов выяснилось, но пониманию-то был поставлен барьер.
математиками обозначающейся всё так же
(оно и понятно почему — на координатных пространствах это покомпонентный предыдущий
, ну кроме того, что структуру абелевой группы там по-другому и не введёшь, а операции таких групп принято повально обозначать
)
Возможно же ещё умножение. Хотя да, читал про некоторые "общепринятые" правила, мол плюс вот здесь, а умножение вот здесь, но ведь при изучении с толку всё равно сбивает. И только потом уже привыкаешь. Вот в вашем примере тоже краткое обозначение
меня попутало (я потом только вспомнил), сначала дописал его как инвариант (просто всплывшее в голове слово), и только потом связал смыл операции с заданием группы, то есть по разнице операций между классами-предками понял, что это скорее
(обратное значение, как и операция - выдающая обратное значение). Как говорят - краткость, конечно же сестра таланта, но в некоторых случаях талантам от этого ничуть не лучше :)
class HasPlus a b c | a b -> c where (+) :: a -> b -> c
Это псевдо-код? А то ведь не хаскель.
Вообще же такой класс может быть полезен, если мы собираемся определить действие абелевой группы на каком-то произвольном типе — такое «сложение» не будет сводиться ни к какому сложению элементов никакой группы самой по себе, так что придётся делать более общий класс
Общие классы полезны, так что стоит их делать. Обязывающая декларация функции далее реализуется наследниками. При этом все, кто взялся делать наследников, понимают, что они делают именно абелеву группу, потому что об этом им напоминает класс-предок.
Плюс алгебраического подхода к числовым и некоторым другим классам как раз в том, что вытекает мало откровенно плохих последствий, в основном могут быть только проблемы из-за большого числа классов и чего-то подобного, а на уровне семантики будет получаться всё хорошо.
Когда нужно учить множество простых определений, получается препятствие. Они все простые и выводы из них простые (как бывает в теории групп), но без того, что бы вспомнить все нужные определения вывод просто не понять. И без длительного запоминания это невозможно (ну у меня не получилось). Это откровенно плохое последствие. Ну а отображается оно на необходимость определять большое количество классов и прочих структур, просто для того, что бы все эти простые базовые понятия получили отражение в программе.
Кстати вот я читал полгода назад где-то, как придумали типоклассы. Удивительно, насколько это вышло чуть ли не случайно, почти везение, хотя казалось бы к этому могли бы прийти как-то логически и десятилетиями двумя раньше.
Там стояла задача что-то сделать с перегрузкой операций при работе с числами (любого типа). Это начали обсуждать, потом в процессе обсуждения один недопонял другого, и повернул его слова именно в сторону темы обсуждения, то есть - как изящно побороть перегрузку. По сути причиной стало именно обсуждение. Ну а как там в процессе конкретные слова вылетали - теперь уже какая разница. Пусть даже кто-то что-то недопонял, главное - если бы не обсуждали (не искали бы ответ), то точно не нашли бы решение.
Это всё есть в
A history of Haskell. Тоже, кстати, "paper", в смысле статья, прошедшая как продукт работы "группы товарищей" из ряда университетов.
сочетает идеи и наследования ООП, и мультиметодов
Классы типизированы и проверка аргументов производится на этапе компиляции, а мультиметоды - на этапе выполнения. Разные штуковины. А вот с наследованием - да, по сути одно и то же (если наследование для интерфейсов).