Wpis z mikrobloga

Programirki! Dzisiaj opublikowałem na blogu post opisujący monady. Każdy, kto kiedykolwiek zetknął się z #programowaniefunkcyjne już pewnie słyszał o tych stworkach.

Chciałbym pokazać, że przydają się także, kiedy uskuteczniamy klasyczne #programowanie. Dodatkowo wołam @archlinuxuser bo chciałeś zobaczyć jak ten koncept wytłumaczę:

http://blog.radoszewski.pl/programming/scala/2015/05/31/mighty-monad.html

Post po angielsku, ale pisany językiem raczej prostym (i prawdopodobnie z błędami ;)). Zapraszam i miłej lektury!

Dodatkowo proszę mirków od #haskell aby przyjrzeli się moim przykładom i sprawdzili, czy nie walnąłem tam czegoś głupiego - Haskell nie jest moim natywnym językiem ;)

Przykłady kodu w #scala, ale są bardzo proste do zrozumienia dla każdego kto programuje.
  • 31
@moriturius: Dobry artykuł, plus za nieporównywanie monad do burrito tudzież biurka - te analogie zawsze prędzej czy później sprawiają, żę człowiek ma mętlik w głowie ; F

Co do wołania Mirków od #haskell - nie jestem prawdziwym haskellfagiem (quicksort to szczyt moich możliwości aktualnie), ale spróbuję:
a) wydaje mi się, że z treści artykułu trochę za bardzo wynika powiązanie monad z kolejnością operacji i stanem, na co prawdziwi Haskellowcy by się
@moriturius: Hmm, całkiem przyjemnie napisane, ale cała sekcja "So what does all this means for developers?" jest co najmniej naciągnięta. Czy naprawdę every method that I used above CAN be implemented using one or more flatMap calls? Bo nie jestem pewien, czy cokolwiek poza map. Owszem, te typy, których tam używasz, są monadyczne, ale to jest zbieg okoliczności, i tej monadyczności nie wykorzystujesz w tym przykładzie wcale.

No
a) wydaje mi się, że z treści artykułu trochę za bardzo wynika powiązanie monad z kolejnością operacji i stanem, na co prawdziwi Haskellowcy by się raczej oburzyli (punkty 6. i 9.).


@jaen: Mam wrażenie, że każdy artykuł o monadach będzie miał coś co nie spodoba się haskellowcom :) Głównie dlatego, że monady to dość skomplikowane twory, nawet jeśli ich używanie jest w zasadzie proste. W artykule piszę o tym, że w
Teraz spójrz na ten przykład do którego się odnosisz. To jest dokładnie to samo - zdefiniowaliśmy sobie pewien ciąg przekształceń danych.


@moriturius: Sorry, ale to jest zwykłe złożenie funkcji.
@moriturius: Nie przekonałeś mnie.

Swoją drogą, w przykładzie def main(): Unit = getChar.flatMap(putChar) coś jakby się typy nie zgadzały. getChar.flatMap(putChar) ma być typu Cośtam[Unit], gdyby było typu Unit, to program byłby - w sensie funkcyjnym - pusty.
Nie przekonałeś mnie.


@frax: No trudno, szkoda.

Swoją drogą, w przykładzie def main(): Unit = getChar.flatMap(putChar) coś jakby się typy nie zgadzały.


@frax: Jeśli patrzysz na to funkcyjnie to - tak, nie zgadzają się. W Scali jednak taki program się skompiluje bez problemów bo jeśli funkcja jest typu Unit to wszystko jedno co zwraca.
@moriturius: Ale czy te getChar i putChar zostaną wywołane? Czy to nie powinno być

def main(): Unit = getChar.flatMap(putChar)()
?

Na moje oko (nieobyte ze scalą, przyznaję) twój przykład odpowiada haskellowemu

main = return $ getChar >>= putChar
@moriturius: No, to chyba zależy, czym jest Costam[B], bo przecież może być funkcją? W każdym razie, zachodzi jedno z dwóch:

a) Costam[B] jest funkcją lub opakowaną funkcją - i wtedy wyliczenie wartości getChar.flatMap(putChar) nie ma skutów ubocznych, a dopiero getChar.flatMap(putChar)() je ma.

b) Costam[B] nie jest funkcją i jego wyliczenie (wykonanie flatMap) ma skutki uboczne, ale wtedy jest całkiem przerypane, bo takie flatMap nie spełnia praw monadycznych dla operacji
@moriturius: Żeby była jasność: nie twierdzę, że twój przykład się nie skompiluje, tylko że albo zakończy się bez żadnej interakcji, albo okaże się, że getChar flatMap wcale nie jest monadą.

Swoją drogą, warto byłoby zauważyć, że jeden typ danych może potencjalnie być monadą na różne sposoby, tzn. z różnie zdefiniowanymi return i >>= czy też unit i flatMap.
@moriturius: Jeżeli getChar.flatMap ma być prawidłową funkcją bind, to nie może mieć skutków ubocznych (bo musi być przemienna). getChar.flatMap jest jedyną funkcją wywołaną przez twoją funkcję main, zatem main nie ma skutków ubocznych. QED
@frax: Dlatego też pisałem w artykule, że developerów nie interesują tak bardzo prawa monad - bardziej to co z nich płynie. Np. w Scali jest monada Try, która oczywiście nie jest monadą bo nie spełnia warunków. Jednak sposób jej użycia jest monadopodobny i w uproszczeniu mówi się, że jest bo te braki nam nie przeszkadzają :)