Рубрики
Без рубрики

Сборник статей: Монады для функционального программирования

Вадлер, Филип, 2001 Прочитал этот пост на испанском Монады – один из многих недостатков… Помечено функциональными, обучающими, java, документами.

Вадлер, Филип , 2001 Прочтите этот пост на испанском языке

Монады – одна из многих концепций, разделяемых математикой и функциональным программированием. Он исходит из теории категорий для решения таких проблем, как контроль исключений, счетчики или трассировки выполнения. Эти проблемы легко решить на императивных языках, но на чистых языках это может быть немного сложнее.

Чисто функциональные языки обладают этим преимуществом: весь поток данных делается явным. И этот недостаток: иногда он бывает болезненно явным.

В документе объясняется, как этот явный поток данных улучшает модульность и важность этой функции в программировании.

В документе объясняется, как этот явный поток данных улучшает модульность и важность этой функции в программировании.

Монада, также называемая стандартной конструкцией, представляет собой структуру данных, которая инкапсулирует поведение. Такое поведение обычно реализуется как побочные эффекты в императивном программировании. Ключевым примером для понимания монад является истинное значение в Scala или VAVR (функциональные структуры данных для JAVA), которые инкапсулируют исключения. Это значение можно использовать для составления функций без явного управления каждой возможной ошибкой до окончательного применения.

public static Try divide(Integer dividend, Integer divider) {
      return Try.of(() -> dividend/divider);
  }

  public static void main(String[] args) {
      Try result = divide(100, 0).flatMap(r1 -> divide(r1, 10));
      System.out.println("RESULT 1 = " + resultado.map(String::valueOf)
       .getOrElseGet(Throwable::getMessage));
       // RESULT 1 = / by zero

      result = divide(100, 10).flatMap(r1 -> divide(r1, 10));
      System.out.println("RESULT 2 = " + resultado.map(String::valueOf)
       .getOrElseGet(Throwable::getMessage));
       // RESULT 2 = 1

  }

Законы Монад

Формальное определение монады включает 3 закона, определяющих, является ли структура монадой. Эти законы, возможно, имеют больше теоретической, чем практической ценности, но этот блог посвящен статье: P поэтому я попытаюсь объяснить принципы.

Левая единица измерения/Левая идентичность

Этот закон гласит, что применение функции к значению и применение ее к монаде с одинаковым значением внутри должно быть одинаковым, если вы используете правильную композицию (карту или плоскую карту в соответствии с возвращением функции).

  public static void main(String[] args) {
      Integer hundred = 100;
      Try tryHundred = Try.of(() -> hundred);
      Boolean r = tryHundred.flatMap(value -> divide(100, value))
      .equals(divide(100, hundred));
      // True
  }
  return a >>= f = f

Правильное подразделение/Правильная идентичность

Как и в предыдущем законе, если у нас есть функция, которая получает значение и инкапсулирует результат в монаде, результат применения ее к значению или объединения ее с другой функцией монады должен быть одинаковым.

  public static void main(String[] args) {
      Integer hundred = 100;
      Try tryHundred = Try.of(() -> hundred);
      // success return the same value encapsulated in a Try but cannot catch exceptions
      Boolean r = tryHundred.flatMap(value -> Try.success(value))
      .equals(Try.success(hundred));// True
  }
  m >>= return = m

Эти примеры в JAVA, по-видимому, имеют одинаковую реализацию, но разница между обоими законами более очевидна в Haskell. Как я уже сказал, эти законы – риторика, а Хаскелл чисто функционален и более близок к математике.

Ассоциативность

Закон ассоциативности гласит, что мы должны иметь возможность составлять функции последовательно или вызывать одну в качестве входных данных другой.

public class MonadTest {

  public static Try divideByTen(Integer dividend) {
      return Try.of(() -> dividend/10);
  }

  public static Try doubleVal(Integer n1) {
      return Try.of(() -> n1 * 2);
  }

  public static void main(String[] args) {

      Try tryHundred = Try.of(() -> 100);
      Try r1 = tryHundred.flatMap(MonadTest::divideByTen).flatMap(doubleVal::doubleVal);
      Try r2 = tryHundred.flatMap(
                        hundred -> divideByTen(hundred).flatMap(MonadTest::doubleVal)
                        );
      Boolean r = r1.equals(r2);// True

  }

}
  (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)

Оригинал: “https://dev.to/gustavo94/digest-of-papers–monads-for-functional-programming-47fp”