2016-07-21 4 views
6

Patrząc na ten kod IO:Trzecie prawo monolityczne i IO?

Prelude> let e = return() :: IO() 
Prelude> e `mappend` e 
Prelude> let y = e `mappend` e 
Prelude> :t y 
y :: IO() 

EDIT Podobno, jak rozumiem, IO ma instancję Monoid.

Czy jednak nie należy oceniać wartości true, aby zastosować się do monolitycznego trzeciego poziomu?

Prelude> e `mappend` (e `mappend` e) == (e `mappend` e) `mappend` e 

<interactive>:14:1: error: 
    * No instance for (Eq (IO())) arising from a use of `==' 
    * In the expression: 
     e `mappend` (e `mappend` e) == (e `mappend` e) `mappend` e 
     In an equation for `it': 
      it = e `mappend` (e `mappend` e) == (e `mappend` e) `mappend` e 

Odpowiedz

11

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.

+5

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

+1

@dfeuer Nie widzę problemu. W końcu mamy instancję 'Eq [a]'. –

+0

@ReinHenrichs, masz rację! – dfeuer