Асинхронный вызов внутри Map() или Bind() для Option (функциональное программирование на C#)C#

Место общения программистов C#
Ответить
Anonymous
 Асинхронный вызов внутри Map() или Bind() для Option (функциональное программирование на C#)

Сообщение Anonymous »

Обратите внимание: если вам кажется, что этот пост длинный, то более половины его — это просто справочный код для завершения.
Я начал изучать функциональное программирование на C#, в основном через эту книгуи это руководство
Итак, я реализовал опцию с методами расширения Map и Bind. Пока все хорошо.
Допустим, я хочу сначала построить конвейер с некоторой фильтрацией, затем вызвать асинхронный метод, а затем продолжить обработку с результатом. Например:
Хорошо, этот псевдокод не очень полезен, но, надеюсь, он показывает, что я имею в виду. Я хочу
сначала сделать цепную замену "if name == Kalle". Тогда, если да, получите продукты из асинхронного метода и еще немного обработайте. Однако первая карта вернет Option
, и мне придется ждать его внутри второй карты... некрасиво.
Option cust = Some(new Customer(){Name ="Kalle"});
cust.Bind(NamedKalle) //yes I could use where here, not the point though :)
.Map(async c => await myHttpClient.GetAdressAsync(c))
.Map(addressTask=> (await addressTask).DoSomethingMore(address))
//...

public Customer NamedKalle(Customer c) =>
c.Name == "Kalle" ? Some(c) : None;

Мне удалось создать асинхронное сопоставление и асинхронную карту, которые, кажется, работают, но я этого не видел, что заставляет меня думать, что я что-то упускаю. Могу ли я использовать оригинальную карту и каким-либо образом привязать ее?
// Match that awaits (member on Option)
public async Task MatchAsync(Func noneFunc, Func someFunc) =>
IsSome
? await someFunc(_value)
: await Task.FromResult(noneFunc());

// Map that awaits, extension method
public static async Task MapAsync(this Option optT, Func func) =>
await optT.MatchAsync(
()=> F.None,
async v => F.Some(func(await v)));


НИЖЕ ТОЛЬКО ДЛЯ СПРАВКИ, это реализация Option, помощников и метода расширения. Это подмножество проекта с открытым исходным кодом по адресу https://github.com/la-yumba/functional-csharp-code/
.namespace ProductCatalog.Api.Functional
{
public static class FunkyExtensions
{
public static Option Map(this Option opt, Func func) =>
opt.Match(() => F.None, v => F.Some(func(v)));

public static async Task Map2(this Option optT, Func func) =>
await optT.Match2(
()=> F.None,
async v => F.Some(func(await v)));

public static Option Where(this Option opt, Func pred) =>
opt.Match(() => F.None,
t => pred(t) ? opt: F.None);

public static Option Bind(this Option opt, Func func) =>
opt.Match(() => F.None, (v) => func(v));

}

public static partial class F
{
public static Option Some(T value) => new Option.Some(value); // wrap the given value into a Some
public static Option.None None => Option.None.Default; // the None value
}

public struct Option
{
T _value;
public bool IsSome { get; set; }
public bool IsNone => !IsSome;
public override string ToString() => IsNone ? $"👍({_value})" : $"👎({_value})";
private Option(T value)
{
if (value == null)
throw new Exception("Cant be null");

_value = value;
IsSome = true;
}

public static implicit operator Option(Option.None _) => new Option();
public static implicit operator Option(Option.Some some) => new Option(some.Value);
public R Match(Func noneFunc, Func someFunc) =>
IsSome ? someFunc(_value)
: noneFunc();

public async Task Match2(Func noneFunc, Func someFunc) =>
IsSome
? await someFunc(_value)
: await Task.FromResult(noneFunc());

}

namespace Option
{
public struct None
{
internal static readonly None Default = new None();
}
public struct Some
{
public T Value { get; set; }
public Some(T value)
{
if (value == null)
throw new Exception("Value should not be null when creating Some, use None instead");
Value = value;
}
}
}
}


Подробнее здесь: https://stackoverflow.com/questions/707 ... mming-in-c
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»