Финальный эффект распространения без тегов - PullRequest
0 голосов
/ 20 февраля 2019

Шаблон tagless-final позволяет нам писать чисто функциональные программы, в которых подробно рассказывается о необходимых им эффектах.

Однако масштабирование этого шаблона может стать сложной задачей.Я постараюсь продемонстрировать это на примере.Представьте себе простую программу, которая читает записи из базы данных и выводит их на консоль.Нам потребуются некоторые пользовательские классы типов Database и Console, в дополнение к Monad от cats / scalaz для их составления:

def main[F[_]: Monad: Console: Database]: F[Unit] =
  read[F].flatMap(Console[F].print)

def read[F[_]: Functor: Database]: F[List[String]] =
  Database[F].read.map(_.map(recordToString))

Проблема начинается, когда я хочу добавить новыйэффект на функцию во внутренних слоях.Например, я хочу, чтобы моя функция read регистрировала сообщение, если записи не были найдены

def read[F[_]: Monad: Database: Logger]: F[List[String]] =
  Database[F].read.flatMap {
    case Nil => Logger[F].log("no records found") *> Nil.pure
    case records => records.map(recordToString).pure
  }

Но теперь мне нужно добавить ограничение Logger для всех вызывающих read доцепь.В этом надуманном примере это просто main, но представьте, что это несколько уровней сложного реального приложения.

Мы можем рассмотреть эту проблему двумя способами:

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

Хотелось бы узнать ваше мнение об этом.

Спасибо.

1 Ответ

0 голосов
/ 20 февраля 2019

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

Я действительно верю в обратное.Одним из ключевых обещаний чистого FP является эквациональное рассуждение как средство извлечения реализации метода из его сигнатуры.Если read для ведения бизнеса нужен эффект регистрации, то он обязательно должен быть декларативно выражен в подписи.Еще одним преимуществом явного описания ваших эффектов является тот факт, что, когда они начинают накапливаться, возможно, нам нужно переосмыслить, что делает этот конкретный метод, и разделить его на более мелкие компоненты?Или этот эффект действительно должен использоваться здесь?

Это правда, что эффекты складываются, но, как упоминалось в комментариях @TravisBrown, обычно это самое высокое место в стеке вызовов, которое должно "страдать от последствий"на самом деле предоставить все неявные доказательства для всего дерева вызовов.

...