The third monoid law stwierdza, że e <> (e <> e) = (e <> e) <> e
(użyć operatora Infix łatwiejszy w rodzaju dla mappend
) nie że e <> (e <> e) == (e <> e) <> e
(uwaga =
Vs. ==
).
To wyrażenie równoważności - naprawdę, wyrażając że mappend
powinny być asocjacyjne - nie wymagający wszystkie Monoid
s musi być również instancje Eq
typeclass, gdzie ==
pochodzi.
Innym sposobem na powiedzenie tego: jest wyrażanie wysokiego poziomu pomysłu na temat zachowania funkcji mappend
, nieprezentowanie prawidłowego kodu Haskella, który powinien oceniać wszystko w szczególności.
Niektóre typy, które są na przykład Monoid
s - np. [()]
- również mają instancję Eq
. Ale niektóre (na przykład instancja IO()
) nie, i to jest w porządku.
Sidenote: To naprawdę nie ma sensu dawać IO
instancję Eq
, ponieważ jest to prawie niemożliwe, aby określić, czy dany IO()
jest odpowiednikiem innej IO()
. Czy putStrLn "3"
jest "równy" z print 3
? Oba mają takie same obserwowalne efekty, ale jak, na ziemi, środowisko wykonawcze może to określić w ogólnym przypadku? Nie można powiedzieć, że "są one równoważne, jeśli wytwarzają te same wartości", ponieważ wtedy typem zwrotu ==
musiałby być IO Bool
, a to nie jest właściwy podpis dla Eq
. Więc po prostu nie dajemy instancji IO
i Eq
i nie ma problemu - nie mogę podać rozsądnego przykładu, kiedy taka instancja byłaby przydatna.
Należy również zauważyć, że „IO
” nie ma instancji Monoid
(to zły rodzaj, w każdym razie). Numer mappend
, którego używasz, pochodzi z instancji dla Monoid a => Monoid (IO a)
— czyli receptur IO do tworzenia typów, które same są Monoid
s. IO
's instancja Monoid
po prostu "piggy-backs" na podstawowej instancji Monoid
.
Poprawna, intuicyjnie poprawna instancja "Eq (IO a)" byłaby * niesamowicie * użyteczna, gdyby można było ją napisać. Ale Alan Turing usiądzie w grobie i zaatakuje cię językiem, jeśli spróbujesz. – dfeuer
@dfeuer Nie widzę problemu. W końcu mamy instancję 'Eq [a]'. –
@ReinHenrichs, masz rację! – dfeuer