Без названия
lex_kravetski — 04.02.2025
Тут между делом речь в комментах зашла про «кольца» и прочие
попытки математиков в обобщения, кои математики продолжают
зафейливать, несмотря даже на то, что программисты с ними давно уже
справились.И вот что тут подумалось. В довольно многих языках сейчас есть те или иные способы потребовать от некого типа что-то вроде «контракта». То есть сказать «наша функция работает для вашего типа, только если для него определена операция plus». Ну и компилятор, соответственно, будет проверять, определена или нет.
Однако в большинстве случаев сие сделано так, что проверяется только имя функции и типы её параметров, но не то, как эта функция работает. Не её свойства, то бишь.
Можно потребовать от типа, чтобы для него была реализована функция «plus», но можно ли, чтобы эта функция была реализована так, что plus(a, b) == plus(b, a) для этого типа? Мало ли, быть может, наша функция только при таком раскладе может гарантировать правильность работы.
Подозреваю, с новыми макросами в Scala иногда как-то можно вывернуться, хотя я ещё не проверил, можно ли и чего это будет стоить, однако совершенно точно это не будет интуитивно понятным описанием. А в большинстве других языков к тому нет даже зацепок.
Но вот в Wolfram таки есть способ. Дело в том, что там есть конструкция, означающая, что «функция определена вот так-то, если некоторое условие выполнилось».
f[x_] := x + 1 /; x > 0
f[2] даст 3.
Но что дадут f[-1] или f[a]?
Ну, они дадут f[-1] и f[a]. Поскольку если «функция» не определена, то ничего не трогаем — мало ли, вдруг потом появится дополнительная информация.
Так вот, в этой логике вполне возможно потребовать от plus независимости от порядка слагаемых.
f[a_, b_] := answer /; (plus[a, b] === plus[b, a])
Тройное равно означает «в точности то же самое посимвольно». То есть, фактически, эта конструкция говорит, что «f определена для этих аргументов, если для них некий plus работает так, что от их перестановки не зависит результат». Результат при этом может быть вообще любой — главное, чтобы он не зависел.
Соответственно, если мы определим plus для, например, типа Integer как…
plus[a_Integer, b_Integer] := a + b
…то f[1, 2] даст результат answer, а вот f[x, y] вернёт f[x, y].
Можно пойти дальше. У нас есть таинственные штуки xxx[чего-то там]. Для них plus работает следующим образом.
plus[xxx[a_], xxx[b_]] := {a, b} // Sort
То есть мы кладём то, что написано квадратных скобках в список, а потом его сортируем. Теперь, если в скобках лежит что-то, что можно отсортировать (то есть, фактически, вообще всё — даже неопределённые символы будут просто отсортированы по алфавиту), то…
f[xxx[1], xxx[k]]
…сработает как надо и даст answer.
|
|
</> |
Руководство по выбору нарезного оружия: калибры, типы систем и оценка состояния 
