Podstawy pisania funkcyjnego

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 :)

        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

            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

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.

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.

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ć?

0
fasadin napisał(a):
            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

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

1

A coś takiego?

        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>();
        }

    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());
    }

1 użytkowników online, w tym zalogowanych: 0, gości: 1