Scala fs2: что делают FreeC и Algebra?

Когда я перехожу к реализации потоковых операций fs2, я часто вижу, что там используются fromFreeC и Algebra.

Что именно делают fromFreeC и Algebra? Зачем и когда они нужны?

Вот пример, операция потока fs2 eval, которая оценивает эффекты и возвращает эффективный поток.

def eval[F[_], O](fo: F[O]): Stream[F, O] =
   fromFreeC(Algebra.eval(fo).flatMap(Algebra.output1))

person Lev Denisov    schedule 31.01.2020    source источник
comment
Поскольку вы находитесь в исходном коде, вы увидите, что в конце Stream просто псевдоним типа Free of values. Free - это монада, которая допускает бесконечную рекурсию данных. Кроме того, как и ввод-вывод, это также ADT для обеспечения ленивости, которая является алгеброй. Итак, в конце Stream - это просто структура данных, которая представляет некоторые вычисления, которые интерпретируются во время выполнения для оценки всех побочных эффектов и выдают реальные значения. - Однако, как пользователю, вы не должны особо заботиться об этом, поскольку это деталь реализации. - Отказ от ответственности: я НЕ fs2 участник.   -  person Luis Miguel Mejía Suárez    schedule 31.01.2020
comment
Спасибо за ответ! Думаю, мне нужно узнать больше о ФП, потому что это не совсем понятно для меня.   -  person Lev Denisov    schedule 31.01.2020
comment
Да, для меня то же самое, и, вероятно, в моем объяснении есть пара ошибок. Верно, что вам, возможно, потребуется больше изучить, чтобы понять реализацию Stream, но вам не нужно слишком много разбираться в том, как его использовать.   -  person Luis Miguel Mejía Suárez    schedule 31.01.2020


Ответы (1)


В исходном коде версии 2.1.0 классы Pull, Stream и FreeC были определены следующим образом:

class FreeC[F[_], +O, +R]
class Pull[+F[_], +O, +R](free: FreeC[Nothing, O, R]) 
class Stream[+F[_], +O](free: FreeC[Nothing, O, Unit])

Ключевая проблема заключается в том, что Stream и Pull были ковариантными по параметру F[_], тогда как FreeC - инвариантным. Как следствие, вы не можете применить F параметр Stream или Pull непосредственно к FreeC типу обернутого значения. Чтобы решить эту проблему, мы использовали Nothing в качестве аргумента для FreeC в этих free полях и применили asInstanceOf преобразования между FreeC[Nothing, O, Unit] в FreeC[F O, Unit] и обратно.

Однако в этом запросе на слияние мы сделали класс FreeC ковариантным на F[_], точно так же, как Stream и Pull, поэтому мы могли бы просто определить:

class FreeC[+F[_], +O, +R]
class Pull[+F[_], +O, +R] (free: FreeC[F, O, R])
class Stream[+F[_], +O] (free: FreeC[F O, Unit])

Таким образом, функция fromFreeC была отброшена. Это было включено в выпуск 2.2.0.


При использовании Nothing используется функция системы типов Scala-2: и Any, и Nothing являются поликодированными типами, поэтому их можно применять в качестве аргументов для параметров типа формы A, F[_], A[_[_]] и т. Д.

person Diego E. Alonso-Blas    schedule 31.08.2020