Рубрика «c#. functional style»

Монада «Maybe» через async-await в C# (без Task-oв!) - 1

Обобщенные асинхронные типы возвращаемых значений — это новая возможность появившаяся в C# 7, которая позволяет использовать не только Task в качестве возвращаемого типа асинхронных (async/await) методов, но также и любые другие типы (классы или структуры), удовлетворяющие определенным требованиям.

В то же время async/await — это способ последовательно вызвать некий набор функций внутри некоторого контекста, что является сущностью шаблона проектирования Монада. Возникает вопрос, можем ли мы использовать async/await для написания кода, который будет вести себя так же, как если бы мы использовали монады? Оказывается, что да (с некоторыми оговорками). Например, приведенный ниже код компилируется и работает:

async Task Main()
{
  foreach (var s in new[] { "1,2", "3,7,1", null, "1" })
  {
      var res = await Sum(s).GetMaybeResult();
      Console.WriteLine(res.IsNothing ? "Nothing" : res.GetValue().ToString());
  }
  // 3, 11, Nothing, Nothing
}

async Maybe<int> Sum(string input)
{
    var args = await Split(input);//Нет проверки результата
    var result = 0;
    foreach (var arg in args)
        result += await Parse(arg);//Нет проверки результата
    return result;
}

Maybe<string[]> Split(string str)
{
  var parts = str?.Split(',').Where(s=>!string.IsNullOrWhiteSpace(s)).ToArray();
  return parts == null || parts.Length < 2 ? Maybe<string[]>.Nothing() : parts;
}

Maybe<int> Parse(string str)
    => int.TryParse(str, out var result) ? result : Maybe<int>.Nothing();

Далее я объясняю, как работает этот код ...

Читать полностью »

«Reader» monad through async-await in C# - 1
In my previous article I described how to achieve the "Maybe" monad behavior using async/await operators. This time I am going to show how to implement another popular design pattern "Reader Monad" using the same techniques.

That pattern allows implicit passing some context into some function without using function parameters or shared global objects and it can be considered as yet another way to implement dependency injection. For example:

class Config { public string Template; }

public static async Task Main()
{
    Console.WriteLine(await GreetGuys().Apply(new Config {Template = "Hi, {0}!"}));
    //(Hi, John!, Hi, Jose!)

    Console.WriteLine(await GreetGuys().Apply(new Config {Template = "¡Hola, {0}!" }));
    //(¡Hola, John!, ¡Hola, Jose!)
}

//These functions do not have any link to any instance of the Config class.
public static async Reader<(string gJohn, string gJose)> GreetGuys() 
    => (await Greet("John"), await Greet("Jose"));

static async Reader<string> Greet(string name) 
    => string.Format(await ExtractTemplate(), name);

static async Reader<string> ExtractTemplate() 
    => await Reader<string>.Read<Config>(c => c.Template);

Читать полностью »


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js