Podstawy pisania funkcyjnego

Podstawy pisania funkcyjnego
fasadin
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
  • Postów:4882
0

Piszę sobie funkcyjnie w C# używając Language-ext https://github.com/louthy/language-ext
jakiekolwiek arty lub ksiazki bylby mile widziane, nie moglem znalezc za duzo informacji na temat tej bibloteki (oprocz githuba czy dokumentacji ktora pobieznie przeczytalem)

Moj brak wiedzy uniemozliwia mi rozwiazania prostych przypadkow. Moze ktos bedzie w stanie mi wytlumaczyc tak bym nie mial z podstawami problemow :)

Kopiuj
        public static async Task<Either<Error, T>> ToResponse<T>(this HttpResponseMessage message)
        {
            var content = await message.Content.ReadAsStringAsync();
            if (string.IsNullOrEmpty(content))
            {
                return Error.ServiceUnavailable("Error while handling HttpResponseMessageExt ToResponse");
            }

            return message.StatusCode.IsError() switch
            {
                true => DeserializeError(content) ?? Error.ServiceUnavailable("Error while handling HttpResponseMessageExt ToResponse DeserializeError"),
                false => DeserializeValue<T>(content) ?? throw new InvalidOperationException("Error while handling HttpResponseMessageExt ToResponse DeserializeValue")
            };
        }

chcialbym ten fragment

Kopiuj
            var content = await message.Content.ReadAsStringAsync();
            if (string.IsNullOrEmpty(content))
            {
                return Error.ServiceUnavailable("Error while handling HttpResponseMessageExt ToResponse");
            }

napisac takze funkcyjnie, Probowalem zmieninac na Option<T> czy Match jednak mam problem z tym by z tego chaina byl zwrocony T a nie string

edytowany 2x, ostatnio: fasadin
Zobacz pozostały 1 komentarz
fasadin
Language-ext ma asynchroniczne metody :) więc nie powinno być z tym problem
S9
@AnyKtokolwiek: no własnie nie za bardzo rozumiem, przecież akurat w każdym FP sa jakies rzeczy typu Future, Deferred, Promise czy inne
SW
@Aleksander32: W C# monady i asynchroniczność to dwie odrębne kwestie. O ile taki Optional z biblioteki ładnie mapuje się w synchronicznym przepływie, przy asynchronicznym biblioteka musi zapewniać metody typu MapAsync, które pod spodem zrobią async/await na lambdzie żeby nie wywalić przekazywania kontekstu synchronizacji.
AK
w Javie też (chyba). Jesli użyjesz słowa "funkcyjne" zostanie to zrozumiane jako "funkcyjne natychmiastowe" a nie "funkcyjne asynchroniczne"
S9
W Javie nie ale masz Future z Vavra
elwis
  • Rejestracja:ponad 18 lat
  • Ostatnio:11 dni
4

Nie znam się na C#, ale wygląda mi to na klasyczny (częsty w Javie) problem gdy próbujesz wpasować imperatywne API do programowania funkcyjnego. W takim wypadku bym po prostu zaimplementowałbym taką funkcję imperatywnie i na wyższym poziomie abstrakcji trzymał się programowania funkcyjnego. Zauważ, że musisz najpierw wykonać message.Content.ReadAsStringAsync(), żeby dowiedzieć się czy jest odpowiedź i ją zapisać, jeśli tak. Jeśli API C# nie przewiduje czegoś takiego, to taka funkcja jest spoko, no chyba że jest tu zastosowana jakaś szersza konwencja do zaimplementowania w bardziej ogólny sposób.


Zobacz pozostałe 3 komentarze
elwis
To co napisałeś ma nie wiele z funkcyjnością wspólnego. Nie widzę w nim szczególnych cech takich jak funkcje map, fold; operator match, funkcji lambda, wartości są mutowalne, funkcje nie są czyste. Co dla ciebie tutaj jest niby funkcyjne?
fasadin
potrzebowalbym literatury ;) brakuje mi wiedzy na ten temat
elwis
Rozumiem, w sumie nie wiem co mógłbym polecić w C#, w Lispie prędzej. Może coś napiszę o tym, dobry pomysł w sumie. Dzięki
elwis
@fasadin: Ewentualnie możesz poczytać to: http://it.wiedz.net.pl/elementarz/wstep.html Nie jest to C#, ale kurs jest w duchu programowania funkcyjnego.
fasadin
dzieki :)
Aventus
  • Rejestracja:prawie 9 lat
  • Ostatnio:ponad 2 lata
  • Lokalizacja:UK
  • Postów:2235
1

@fasadin: jeśli chodzi o książki to od siebie mogę polecić Functional Programming in C#. Co prawda nie dokończyłem jej (muszę to nadrobić) a i nie wiem czy puryści FP nie mieliby jakichś zastrzeżeń, ale ogólnie bardzo fajnie mi się czytało.

Co do samego zagadnienia nauki FP to może warto pomyśleć nad przerzuceniem się na inny jezyk? Nie musisz nawet odbiegać od ekosystemu .Net bo możesz przerobić jakiś kurs F#. Ja co prawda tylko to liznąłem ale już sam wstęp pomógł mi lepiej zrozumieć z czym FP tak naprawdę się je. Jakby nie patrzyć to jakikolwiek język FP-first pozwoli przynajmniej w jakimś stopniu uniknąć pewnych nawyków i wymusi inne podejście.


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.
Zobacz pozostały 1 komentarz
fasadin
ksiazka zamowiona ;)
Aventus
@fasadin: z ciekawości- zamawiales bezpośrednio od Manning?
fasadin
Nope
Aventus
Manning ma bardzo fajną politykę dodawania kodów do ebooków wraz z papierową wersją książek. Nie wiem czy ma to miejsce tylko jak się kupuje bezpośrednio od nich czy od każdego dystrybutora.
vpiotr
Jeśli zamawiasz bezpośrednio w Manning to dostajesz potem upusty (do 50%), masz od razu ebooka, kod. Niestety przesyłka nie jest jakaś super tania (chyba od $9) i same książki do najtańszych nie należą. Ale za to myślę że mają całkiem niezły poziom merytoryczny książek - ani nie nudzą dowodami (jak Springer) ani nie są tak banalni jak Packt - są gdzieś pośrodku.
AF
  • Rejestracja:prawie 18 lat
  • Ostatnio:14 dni
0

https://dotnetfiddle.net/c2t8sd

Szału to nie robi moim zdaniem. Ten Either ma jakąś sensowną metodę Return czy coś do zapakowania wartości w left/right, czy muszę rzutować?

obscurity
  • Rejestracja:około 6 lat
  • Ostatnio:2 dni
0
fasadin napisał(a):
Kopiuj
            return message.StatusCode.IsError() switch
            {
                true => DeserializeError(content) ?? Error.ServiceUnavailable("Error while handling HttpResponseMessageExt ToResponse DeserializeError"),
                false => DeserializeValue<T>(content) ?? throw new InvalidOperationException("Error while handling HttpResponseMessageExt ToResponse DeserializeValue")
            };

omg, proszę powiedz że to Twój potworek a nie że zaczęło się przyjmować używanie switcha do sprawdzania boola zamiast operatora warunkowego


"A car won't take your job, another horse driving a car will." - Horse influencer, 1910
Zobacz pozostałe 17 komentarzy
DQ
W przypadku prostych warunków rzeczywiście zazwyczaj używa się if'a - z tym, że to tyczy się języków, które traktują je jako expression, a nie statement. Ogólnie, to użycie switcha zamiast ifa nie jest żadnym wielkim błędem i robienie z tego takiego szumu to zdecydowanie większe WTF niż sam kod.
Aventus
Dzięki @fasadin. @DisQ tu nie chodzi o robienie szumu tylko zwykła ciekawość i punk widzenia kogoś kto na co dzień nie programuje 100% funkcyjnie. Tak czy inaczej dzięki za dołączenie się do dyskusji, chociaż tak naprawdę żadnej odpowiedzi nie uzyskałem- w takim razie czy operator warunkowy ? jest uważany za to samo co if, oraz w czym on jest gorszy od użycia switcha?
fasadin
Aventus nie pytaj mnie. Uczę się dopiero funkcjonalnego. Po prostu tutaj mi (więc to jest opinia, moja) wygląda ładniej (bo pasuje do pattern matching dla either w sensie jest podobne).
DQ
Z szumem bardziej mi chodziło o oryginalny post ;) Jeśli chodzi o tenary operator, to w językach czysto/prawie funkcyjnych w ogóle ich nie ma, a przynajmniej ja nie znam takiego w którym by był. Wynika to z tego, że if/else działają dokładnie tak samo. Więc jest trochę inaczej niż w językach obiektowych, gdzie zazwyczaj if jest statement'em, a tenary expression
DQ
Jeśli chodzi o użycie ?/if/switch dla Boolean, to zazwyczaj jest to kwestia tylko i wyłącznie umowna (zakładając, że if jest traktowany jako expression). W Scali przyjęło się, że do booleanów zazwyczaj stosuje się ifa, ale nie jest to żadna twarda reguła. Jeśli w jakimś kontekście lepiej/ładniej/wygodniej jest użyć switcha to śmiało, nic nie stoi na przeszkodzie bo to nie jest żaden błąd
vpiotr
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
2
fasadin napisał(a):

Piszę sobie funkcyjnie w C# używając Language-ext https://github.com/louthy/language-ext

jakiekolwiek arty lub ksiazki bylby mile widziane, nie moglem znalezc za duzo informacji na temat tej bibloteki (oprocz githuba czy dokumentacji ktora pobieznie przeczytalem)

Nie programuję w MS Javie, ale książka "Functional Programming in C#" bazuje na Language-ext i jest recenzowana przez jej autora (Paula Louth).
Autor książki - Enrico Buonanno - zrobił własną bibliotekę tego typu: LaYumba.Functional
Kody do książki: https://github.com/la-yumba/functional-csharp-code

fasadin
Dzięki wielkie :)
Mikan
  • Rejestracja:ponad 9 lat
  • Ostatnio:10 miesięcy
  • Postów:75
1

A coś takiego?

Kopiuj
        private static Validation<Error, string> NotEmpty(string val) =>
            Optional(val).Where(it => !string.IsNullOrEmpty(it)).ToValidation(new Error());

        private static Func<string, Validation<Error, T>> Deserialize<T>(bool isError) where T : new() =>
            content => isError
                ? (Validation<Error, T>)(DeserializeError(content) ?? new Error())
                : DeserializeValue<T>(content) ?? throw new InvalidOperationException("Error while handling HttpResponseMessageExt ToResponse DeserializeValue");


        public static Either<Error, T> ToResponse<T>(HttpResponseMessage message) where T : new()
        {
            return NotEmpty(message.Content.ReadAsStringAsync().Result)
                .Bind(Deserialize<T>(message.StatusCode.IsError())).ToEither<T>();
        }

Kopiuj
    public static class Ext
    {
        public static Error Join(this Seq<Error> errors) => string.Join("; ", errors);
        public static Either<Error, R> ToEither<R>(this Validation<Error, R> validation) =>
            validation.ToEither().MapLeft(errors => errors.Join());
    }
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)