Информация об изменениях

Сообщение Re[3]: Монады - пример где бы были полезны... от 29.08.2019 10:05

Изменено 29.08.2019 10:07 Jack128

Опечатка

Re[3]: Монады - пример где бы были полезны...
Здравствуйте, takTak, Вы писали:

S>>>Могли бы вы привести пример из жизни, где вы использовали монады не ради академической науки а для облегчения написания/поддержки кода?


S>>>Бывает такое?


J>>Бывает, но в haskel'е. Для того, чтоб монады были полезны на практике нужен high kinded polimorphism, которого в жаба-шарпах нету


T>а можно как-то поподробнее и "на пальцах"?


T>допустим, в яве -шарпах, мне не нравится такой код


T>
T>if (a != null)
T>            {
T>                if (a.Prop1 != null)
T>                {
                    
T>                }
T>            }
T>

T>с помощью Maybe / Option / Either- монад его можно переписать во что-то более удобочитаемое,
T>а о чём именно говоришь ты?

FileStream fileStream = new FileStream(...)
fileStream.WriteString("BlaBla")
как тут поможет обычный полиморфизм ?? да никак. Но он поможет если ты хочешь писать строки и в файл и в сеть и в память.
Так и с монадами. Ну ясно что у тя тут монада Maybe(nullable) — но для упрощения этого кода само понятие монад не нужно, нужно тупо захардкорить в язык операции над nullable (как это сделали в шарпе) и получить a?.Prop?.MyMethod();

А если ты хочешь написать код работающий с любыми монадами — вот тут становится интереснее

Вот тебе пример на псевдо шарпе, который умеет:
1) хай кайндед полимофизм.
2) умеет неявно lift'идь операторы для любого монадического типа, а не только для Nullable<> как сейчас. Тo есть M<int> a, b; a + b — преобразует в a.bind(x => b.bind(y => new M<int>(x + y)))
Теоретически я бы мог использовать query syntax, который суть — аналог do натации в haskel'е, но это сильно раздуло бы код, скрывая смысл.


M<int> Average<M<_>>(IEnumerable<M<int>> ints) {
   var sum = new M(0);
   var count = 0;
   foreach(var v in ints) {
      sum = sum + v;
      count++;
   }
   return count > ? (sum / count) : new M<int>(0);
}


Думаю понятно что эта функция делает.

теперь попробует её использовать:
IEnumerable<int> items = ....;
// Identity - то монада Identity. Хотя опять же для удобства иcпользования можно было бы считать, что любой тип сам по себе является модой Identity, чтоб не делать подобных приседаний
Console.WriteLine(Average(items.Select(x => new Identity(x))));


IEnumerable<Nullable<int>> items2 = File.ReadAllLines("1.txt").Select(TryParseInt); // TryParseInt имеет сигнатуру int? TryParseInt(string s);
Console.WriteLine(Average(items2)); // если какая то строка не является числом - получится null


IEnumerable<Task<int>> items3 = new[] { GetIntAsync("www.google.com"), GetIntAsync("www.bind.com"), GetIntAsync("www.ya.ru") } ;
Console.WriteLine(await Average(items3));
Re[3]: Монады - пример где бы были полезны...
Здравствуйте, takTak, Вы писали:

S>>>Могли бы вы привести пример из жизни, где вы использовали монады не ради академической науки а для облегчения написания/поддержки кода?


S>>>Бывает такое?


J>>Бывает, но в haskel'е. Для того, чтоб монады были полезны на практике нужен high kinded polimorphism, которого в жаба-шарпах нету


T>а можно как-то поподробнее и "на пальцах"?


T>допустим, в яве -шарпах, мне не нравится такой код


T>
T>if (a != null)
T>            {
T>                if (a.Prop1 != null)
T>                {
                    
T>                }
T>            }
T>

T>с помощью Maybe / Option / Either- монад его можно переписать во что-то более удобочитаемое,
T>а о чём именно говоришь ты?

FileStream fileStream = new FileStream(...)
fileStream.WriteString("BlaBla")
как тут поможет обычный полиморфизм ?? да никак. Но он поможет если ты хочешь писать строки и в файл и в сеть и в память.
Так и с монадами. Ну ясно что у тя тут монада Maybe(nullable) — но для упрощения этого кода само понятие монад не нужно, нужно тупо захардкорить в язык операции над nullable (как это сделали в шарпе) и получить a?.Prop?.MyMethod();

А если ты хочешь написать код работающий с любыми монадами — вот тут становится интереснее

Вот тебе пример на псевдо шарпе, который умеет:
1) хай кайндед полимофизм.
2) умеет неявно lift'идь операторы для любого монадического типа, а не только для Nullable<> как сейчас. Тo есть M<int> a, b; a + b — преобразует в a.bind(x => b.bind(y => new M<int>(x + y)))
Теоретически я бы мог использовать query syntax, который суть — аналог do натации в haskel'е, но это сильно раздуло бы код, скрывая смысл.


M<int> Average<M<_>>(IEnumerable<M<int>> ints) {
   var sum = new M(0);
   var count = 0;
   foreach(var v in ints) {
      sum = sum + v;
      count++;
   }
   return count > ? (sum / count) : new M<int>(0);
}


Думаю понятно что эта функция делает.

теперь попробует её использовать:
IEnumerable<int> items = ....;
// Identity - то монада Identity. Хотя опять же для удобства иcпользования можно было бы считать, что любой тип сам по себе является монадой Identity, чтоб не делать подобных приседаний
Console.WriteLine(Average(items.Select(x => new Identity(x))));


IEnumerable<Nullable<int>> items2 = File.ReadAllLines("1.txt").Select(TryParseInt); // TryParseInt имеет сигнатуру int? TryParseInt(string s);
Console.WriteLine(Average(items2)); // если какая то строка не является числом - получится null


IEnumerable<Task<int>> items3 = new[] { GetIntAsync("www.google.com"), GetIntAsync("www.bind.com"), GetIntAsync("www.ya.ru") } ;
Console.WriteLine(await Average(items3));