To nie jest konieczne do tego operator dodawania, ale w ogóle można zrobić funkcją przemienne bez realizacji wszystkich przewracanej przypadki dodając ostateczną równanie, które odwraca argumenty:
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
Jednak minusem jest to, że jeśli zapomnisz obsłużyć przypadek, to łatwo prowadzi do nieskończonej pętli:
adjacent A B = True
adjacent B C = True
adjacent x y = adjacent y x
Tutaj adjacent A C
nazwałbym adjacent C A
, który nazwałbym adjacent A C
, i tak dalej. Wzorzec dopasowania GHC do sprawdzania wyczerpania (-fwarn-incomplete-patterns
lub -Wall
) nie pomoże tutaj.
Chyba można dodać dodatkowy argument, aby zapobiec pętli:
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
Teraz GHC będzie narzekać, jeśli nie dodać równanie go Reverse
obsłużyć przypadek gdzie zamieniono ale nadal nie było meczu.
Ale myślę, że jest to odpowiednie tylko dla funkcji z dużą liczbą przypadków - w przeciwnym razie dużo lepiej jest po prostu wyliczyć je wszystkie.
Można zdefiniować dodawanie normalnie i uzyskać (wolną) komutatywność za darmo. – ThreeFx
Również to już ma odpowiedź [tutaj] (http://stackoverflow.com/questions/29210248/haskell-defining-commutative-functions-how-to-consider-actual-arguments-by-co). (Jest bardziej ogólny niż Twój przypadek użycia, więc prawdopodobnie będziesz musiał przeprowadzić pewne badania, aby skorzystać z sugerowanego pakietu) – ThreeFx
Jeśli weźmiesz pod uwagę leniwość prawie żadna operacja nie jest całkowicie przemienna, ponieważ zazwyczaj 'f niezdefiniowane x' może być inne niż' fx undefined' ze względu na fakt, że dopasowywanie wzorców jest zasadniczo sekwencyjne. Z tego powodu tak trudno jest uzyskać pełną abstrakcję pomiędzy operatywną i denotacyjną semantyką języków funkcjonalnych: w denotacyjnej semantyce włącza się funkcje takie jak równoległe lub itd., Które w rzeczywistości nie mogą być zdefiniowane w języku. – Bakuriu