Ответ 1
Не нужно этого оператора сложения, но в общем случае вы можете сделать функцию коммутативной без реализации всех вскрытых случаев, добавив окончательное уравнение, которое переворачивает аргументы:
data X = A | B | C
adjacent A B = True
adjacent B C = True
adjacent A C = False
adjacent x y = adjacent y x -- covers B A, C B, and C A
Однако недостатком является то, что если вы забудете обработать случай, это легко приведет к бесконечному циклу:
adjacent A B = True
adjacent B C = True
adjacent x y = adjacent y x
Здесь adjacent A C
вызовет adjacent C A
, который вызовет adjacent A C
и т.д. И проверка соответствия шаблону соответствия GHCs (-fwarn-incomplete-patterns
или -Wall
) не поможет вам здесь.
Я думаю, вы могли бы добавить дополнительный аргумент для предотвращения цикла:
data Commute = Forward | Reverse
adjacent = go Forward
where
go _ A B = True
go _ B C = True
go Forward x y = go Reverse y x -- try to commute
go Reverse _ _ = False -- commuting failed
Теперь GHC будет жаловаться, если вы не добавите уравнение go Reverse
для обработки случая, когда вы заменили, но совпадения не было.
Но я думаю, что это подходит только для функций с большим количеством случаев - в противном случае его гораздо яснее просто перечислять их все.