Wyjątki, Either i programowanie funkcyjne

Wyjątki, Either i programowanie funkcyjne
piotrpo
  • Rejestracja:ponad 7 lat
  • Ostatnio:5 dni
  • Postów:3277
1

Idziecie w jakieś filozoficzne rozważania. Funkcja w programowaniu funkcyjnym jest pojęciem prawie tożsamym z definicją matematyczną. Prawie, bo jednak nie wszystkie funkcje są "pure", np. now(), rand().
Program funkcyjny to w założeniu funkcja złożona np. f(g(h(x))), gdzie wynik h(x) jest parametrem g(), a wynik g() jest parametrem f(). Wyjątek rzucony z h() nie zostanie zwrócony jako parametr do g() i do h(). Dlatego rzucanie wyjątkami nie jest zgodne z "duchem" programowania funkcyjnego.

loza_prowizoryczna
Czemu now() i rand() nie są pure?
piotrpo
Bo zwracają wyniki niezależne od przyjmowanych parametrów. W każdym razie tak to widzę.
loza_prowizoryczna
Teoretycznie można założyć że parametrem funkcji jest tutaj zbiór. Nie do końca czaję jak mogła by wyglądać funkcja definiująca nieograniczony zbiór czasu i liczb. To dalej byłaby funkcja bezparametrowa.
jarekr000000
@loza_prowizoryczna: nie jestem w stanie zrozumieć co piszesz i jak się to ma do dyskusji wyżej - jaka funkcja definiująca nieograniczony zbiór czasu i liczb????
loza_prowizoryczna
@jarekr000000: Dobrze że chociaż zadajesz pytania, niektórzy poprzestają na pierwszym ;) funkcja definiująca nieograniczony zbiór czasu i liczb - jeśli zdefiniuję sobie funkcję f(x) = 1 to równie dobrze mogę zdefiniować sobie funkcję f(x) = R gdzie R to zbiór liczb rzeczywistych. Dla funkcji rand pure wyglądało by wtedy tak: rand(f(x)) tyle że x jest wówczas zbyteczny bo f(x) jest stałą i zawsze zwraca ten sam element.
jarekr000000
@loza_prowizoryczna: nic to nie zmienia - rand(f(x)) nadal nie jest pure funkcją ( o ile tylko rand(R) nie zwraca zawsze tej samej wartości, strzelam, że rand zwracający tą samą wartość to nie jest coś o co Ci chodzi. Aczkolwiek można mieć pseudolosowość w pure fp. Jest kilka spososbów np. rand(acc) -> (x,new acc) (za każdym razem dostajemy parę - wartość pseudolosową, i "akkumulator/stan" do wstawienia przy nastepnym wywołaniu.
loza_prowizoryczna
Od kiedy wybór w matematyce przekreśla czystość funkcji?
jarekr000000
@loza_prowizoryczna: https://en.wikipedia.org/wiki/Function_(mathematics) - są różne definicje, ale zasadniczo dla kazdego elementu z dziedziny masz jeden element z przeciwdziedziny. Jeśli twoją przeciwdziedziną są np. zbiory liczb, to oczywiście możesz nawet sobie dla pewnego x zwracać całe R, ale zwracasz to jedno całe R zawsze, a nie raz jeden element z R, innym razem inny.
piotrpo
Zdaje się, że istnieją implementacje rand(x), które są funkcjami. Pisząc rand() miałem na myśli pobranie ziarna z zewnątrz (np. now()).
loza_prowizoryczna
@jarekr000000: Dla uproszczenia przyjmijmy że operujemy na zbiorach zawsze. Dana jest więc funkcja f(x) zwracająca zbiór R. Oprócz tego mamy funkcję rand(f(x) która jest selektorem - dokonuje wyboru ze zbioru f(x) zwracając jego jednoelementowy podzbiór. Jeśli f(x) zwróci zbiór jednoelementowy to funkcja rand(f(x)) zwróci ten sam zbiór. Jeśli f(x) będzie zbiorem dwuelementowym to rand(f(x) zwróci dowolny podzbiór jednoelementowy. Wybór nie jest deterministyczny.
jarekr000000
Pisanie coraz większego i dłuższego bełkotu nie sprawi, że to co piszesz zacznie mieć sens.
loza_prowizoryczna
A czego nie rozumiesz? Że może istnieć czysta funkcja które nie jest deterministyczna dla danego argumentu?
piotrpo
No nie bardzo może istnieć "czysta niedeterministyczna funkcja". rand(x) nie jest niedeterministyczne. Możesz zrobić funkcję rand(X, y), gdzie pierwszy parametr jest zbiorem, a drugi jest ziarnem ciągu pseudolosowego. Funkcja jest pure, ale jest też deterministyczna. rand(X, y) -> X[rand(y)]. Możesz też nie przekazywać ziarna i mieć rand(X, y) -> X[rand(now())] i wtedy będzie niedeterministyczna (co już oznacza, że nie jest funkcją), w dodatku nie jest "pure", bo pobiera dane z boku (zegar systemowy, albo inne źródło niby losowe).
loza_prowizoryczna
Pseudolosowość != losowość. W tym cały trik że za bardzo tego drugiego nie możemy skutecznie zamodelować algorytmicznie stąd mamy specjalizowane instrukcje do tego w większości CPU (ziarno pochodzi z natury). Ale wciąż omijasz clue problemu - że funkcja rand jest de facto funkcją wyboru. A że aksjomat wyboru zaprzecza aksjomatowi determinacji z definicji to cała nasza dyskusja sprowadza się do stwierdzenia - który zbiór aksjomatów uznajemy.
jarekr000000
@loza_prowizoryczna: nadal bredzisz. To nic nie ma do aksjomatu wyboru. Oczywiście możesz sobie stworzyć jakąś swoją definicję funkcji - jest tony różnych formalizmów. Ale standardowo funkcja przyporządkowuje jeden deterministyczny element z przeciwdziedziny. (zobacz Formalna definicja z https://pl.wikipedia.org/wiki/Funkcja - > istnieje dokładnie jeden y z Y . Ten element to może być zbiór oczywiście. Nic to nie zmienia.
loza_prowizoryczna
W takim razie jak zdefiniować formalistycznie funkcję selektora?
jarekr000000
A musi to być funkcja?
loza_prowizoryczna
Heh, w sumie nie, tylko wtedy powstaje pytanie - czy da się sformalizowanym językiem funkcyjnym opisać rzeczywistość gdzie głównym problemem jest wybór. Bo jeśli nie to poza możliwością prostszego dowiedzenia jego poprawności jakie są jego przydatności w praktyce?
jarekr000000
Możesz przetłumaczyć? nie chce mi się w chatgpt wpisywać
loza_prowizoryczna
Jak zakodzić choćby taki zwykły algorytm kryptograficzny bazujący na losowym ziarnie używają formalizmu funkcyjnego.
jarekr000000
Jeśli chodzi Ci o to, czy można w języku funkcyjnym operować na zmiennych losowych to jak najbardziej. Wystarczy zobaczyć jak jest metematycznie zdefiniowana zmienna losowa (jako funkcja od zbioru zdarzeń). (Przykład pokazywałem wyżej - można w to nawet wrzucić losowość z zewnątrz: losuj(zewnątrz) -> (użyte_zewnątrz, rezultat)
jarekr000000
Ta takim haskellu to zewnątrz jest zapisywane jako IO m.(np. IO Int = mam inta, dzięki temu, że działałem z jakimś zewnątrz (np. wylosowane, użytkownik wpisał etc).
GO
@loza_prowizoryczna: w algorytmach zwykle się nie dodaje ziaren tylko czas, wtedy serwer widzi, że jak 10 sekund temu było wysłane zapytanie to jest to prawdziwe, a jak przekroczy to ktoś jakiś replay attack zastosował, zwykle to dużo nie znaczy, ale jak masz bramę od domu to obroni cię przed takim atakiem, gdzie ktoś ci otworzy bramę tydzień później bo nagrał jak otwierasz bramę, a ten kod już będzie miał nieważny timestamp.
loza_prowizoryczna
jak jest metematycznie zdefiniowana zmienna losowa (jako funkcja od zbioru zdarzeń) - czyli jednak da się zdefiniować matematycznie funkcję selektora i jest to czysta funkcja? Haskell mnie nie interesuje, nie trawię Comic Sans nawet wrzucić losowość z zewnątrz - to jest jedyne prawilne rozwiązanie nie naruszające formalizmu. Ale wtedy masz system otwarty.
jarekr000000
@loza_prowizoryczna: funkcja w zmiennej losowej jest deterministyczna :-)
loza_prowizoryczna
@jarekr000000: No brawo, mamy zmienną losową deterministycznie spełniającą dla każdej wartości gwarancję prawdopodobieństwa równą liczbie elementów z wyboru. Tylko teraz co z teraz now()? Wg. definicji każda powinna zwrócić unikalną wartość ;)
jarekr000000
@loza_prowizoryczna: Tylko teraz co z teraz now()? Wg. definicji każda powinna zwrócić unikalną wartość 😉 gdzie masz taką definicję? i co to jest to now()?
loza_prowizoryczna
@jarekr000000: Definicję masz w nazwie. A jak nie rozumiesz dlaczego powinna zwrócić unikalną wartość to może warto się zastanowić nad problemem równoczesności.
jarekr000000
@loza_prowizoryczna: co ma to wspólnego z matematyczną funkcją? co mi da zastanawianie się nad problemem równoczesności? (tyle jest innych problemów)
loza_prowizoryczna
@jarekr000000: co ma to wspólnego z matematyczną funkcją? W sumie tyle samo co czysta matematyka ze stosowaną. Tą pierwszą się bawimy, tej drugiej używamy. co mi da zastanawianie się nad problemem równoczesności? - pewnie nic, funkcji ze stdbliba się używa, od problemów z ich implementacjami są ci co się bawią.
jarekr000000
@loza_prowizoryczna: akurat ukończyłem matematyke stosowaną. Opiera się zasadniczo na czystych matematycznych funkcjach :-) To, że nie ogarniasz to nie oznacza, że się nie stosuje.
piotrpo
Ale wam się dyskusja rozwinęła. now() nie pasuje do matematycznej definicji funkcji. Matematyka nie przewiduje, żeby jakieś wyrażenie algebraiczne zwracało dla tych samych danych różne wyniki (albo nie dotarłem do tej części matematyki). Tylko programowanie to inżynieria, a nie matematyka.
loza_prowizoryczna
@jarekr000000: Opiera się zasadniczo na czystych matematycznych funkcjach - no to nie dziwię się że czasami możesz mieć problem z definicjami. @piotrpo: jakieś wyrażenie algebraiczne zwracało dla tych samych danych różne wyniki - ja wciąż się zastanawiam jak oni wszyscy notują wyrażenie selektora (czyli aksjomat wyboru). Bo selektor z natury zwraca podzbiór ale jego zachowanie może być definiowane zewnętrznie. Jak żyć?
piotrpo
Prosto, przekazujesz ten wybór jako zmienną.
loza_prowizoryczna
Ale zmienne mają side-effects
SL
  • Rejestracja:około 7 lat
  • Ostatnio:około godziny
  • Postów:876
0

@piotrpo zakładając, że rzucone wyjątki są częścią return value to nie widzę powodów dlaczego wyjątki mogą nie być pure. Zarówno mamy zachowaną czystość (ten sam wynik dla tych samych argumentów) jak i referential transparency (wykluczając oczywiście stack traces)

piotrpo
  • Rejestracja:ponad 7 lat
  • Ostatnio:5 dni
  • Postów:3277
3

Ale cała dyskusja toczy się wokół wyższości Wielkanocy nad Gwiazdką either nad throw. Zwracanie wyjątku w postaci return value, czyli opakowanego w either oznacza, że funkcja zwraca wciąż tę samą strukturę, jedynie z innymi wartościami. W matematyce przecież funkcja również nie musi zwracać koniecznie liczby rzeczywistej, może być liczba złożona, tensor czy inny kwaternion.

Zobacz pozostałe 5 komentarzy
piotrpo
Chodzi ci np. o takie f(x), które dla x<0 zwraca g(x), a dla x >= 0 h(x)?
loza_prowizoryczna
Nie, przecież to jest funkcja ciągła ;)
piotrpo
No ok, to co z tym 1/x?
loza_prowizoryczna
Ok, teraz załapałem, 1/x też jest nieciągłe dla wartości 0. Ale w sumie cały wątek jest o tym mowa - bo Either jest przykładem funkcji złożonej.
jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około godziny
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
1
slsy napisał(a):

@piotrpo zakładając, że rzucone wyjątki są częścią return value to nie widzę powodów dlaczego wyjątki mogą nie być pure. Zarówno mamy zachowaną czystość (ten sam wynik dla tych samych argumentów) jak i referential transparency (wykluczając oczywiście stack traces)

Tak, wyjątki zwrócone przez return value są zasadniczo pure.

Impure jest tylko jak są rzucone przez throw.


jeden i pół terabajta powinno wystarczyć każdemu
GO
Masz na myśli return new Exception zwrócić obiekt exceptiona returnem? nigdy czegoś takiego nie widziałem na oczy.
jarekr000000
@.GodOfCode.: to nawet nie jest specjalnie dziwna konstrukcja.
GO
Wiem, że to zadziała, ale dziwne to
99xmarcin
  • Rejestracja:prawie 5 lat
  • Ostatnio:4 miesiące
  • Postów:2420
0

powoduje side-effect, więc funkcja nie jest już 'pure'

Jeżeli wyjątek powoduje site effect to return tym bardziej go powoduje. Jeżeli wyjątek powoduje terminacje programu to tym bardziej wyjście z metody main.

powoduje, że tracimy 'referential transparency'

Tego punktu nie łapę, można zastąpić foo() throw new FooException() i będzie Git. Nie można tutaj mówić że nie spełnia referential transparency.

Niestety jest to 99 wątek tego rodzaju na 4p. Moderacja powinna wziąć się do roboty i zacząć stemplować [Duplicate] tak jak to robią na SO...


Holy sh*t, with every month serenityos.org gets better & better...
lion137
  • Rejestracja:około 8 lat
  • Ostatnio:mniej niż minuta
  • Postów:4891
2

Jeżeli wyjątek powoduje site effect to return tym bardziej go powoduje.

Jak, return to normalne wyjście z funkcji i nie powoduje side effects, za to wyjątek jak najbardziej.

Tego punktu nie łapę, można zastąpić foo() throw new FooException() i będzie Git.

Co będzie git, przecież jeśli oczekujemy wyniku, np. liczby, to tracimy referential transparency, chyba, że zawsze rzucamy wyjątek.


jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około godziny
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
1
99xmarcin napisał(a):>

Tego punktu nie łapę, można zastąpić foo() throw new FooException() i będzie Git. Nie można tutaj mówić że nie spełnia referential transparency.

Nie można. Referential transparency oznacza, że możesz zamienić wywołanie funkcji przez wartość funkcji w punkcie. throw new FooException() nie jest wartością. Nie możesz np. podstawić tego pod zmienną. Możesz podstawić samo new FeeException() ale to już będzie działać inaczej.

Niestety jest to 99 wątek tego rodzaju na 4p. Moderacja powinna wziąć się do roboty i zacząć stemplować [Duplicate] tak jak to robią na SO...

Raczej powinniśmy pisać. Było, użyj opcji szukaj. Dzięki temu odbudujemy popularność portalu.


jeden i pół terabajta powinno wystarczyć każdemu
edytowany 2x, ostatnio: jarekr000000
KA
  • Rejestracja:ponad 3 lata
  • Ostatnio:5 miesięcy
  • Postów:7
1

@jarekr000000: Tak przeszukiwałem całe forum w poszukiwaniu odpowiedzi na swoje pytanie, ale im dłużej czytałem tym mniej byłem pewien co jest prawdą a co nie. W każdym razie dziękuję wszystkim za opinie - wybiorę sobie z nich swoją wersje prawdy.

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)