Size: a a a

Scala User Group

2021 September 16

EK

Evgenii Kuznetcov in Scala User Group
Люди спорят, сколько дырок достаточно каждому программисту.
А были ли попытки сделать дырко-полиморфные системы эффектов?
источник

EK

Evgenii Kuznetcov in Scala User Group
polysemy вроде подходит
источник

Oℕ

Oleg ℕizhnik in Scala User Group
не полисеми, не дыркополиморфная
источник

Oℕ

Oleg ℕizhnik in Scala User Group
но точно так же, как любые функции можно свести к функциям одного аргумента, любое количество дырок любого кайнда можно свести к одной дырке
источник

Oℕ

Oleg ℕizhnik in Scala User Group
через субвселенные тегов
источник

Oℕ

Oleg ℕizhnik in Scala User Group
т.е. ну хотите вы, допустим сделать вашу штуку полиморфную относительно трёх параметров например так
trait Foo[X, Y[_, _], Z[_[_]]]
источник

Oℕ

Oleg ℕizhnik in Scala User Group
вы на самом деле можете сделать
trait Foo[F[_]]
объявить типы

class XTag
class YTag[A, B]
class ZTag[F[_]]
и дальше внутри трейта сделать соответствующие замены
X -> F[XTag]
Y[A, B] -> F[YTag[A, B]]
Z[F] -> F[ZTag[F]]
источник

Oℕ

Oleg ℕizhnik in Scala User Group
затем при подстановке вам нужно было бы придумать специальное семейство
т.е. например вместо того, чтобы явно подставить
X -> Int
Y[A, B] -> Either[A, B]
Z[F[_]] -> Ref[F, String]

в скале 2 вам пришлось бы придумывать специальное семейство

sealed trait Subst[Tag]
case class XSubst(i: Int) extends Subst[XTag]
case class YSubst[A, B](e: Either[A, B]) extends Subst[YTag[A, B]]
case class ZSubst[F[_]](r: Ref[F, String]) exends Subst[ZTag[F]]

и это сработало везде, где вы можете решить проблему с помощью изоморфизма

а в скале 3 гораздо проще

type Subst[Tag] = Tag match
   case XTag => Int
   case YTag[a, b] => Either[a, b]
   case ZTag[f] => Ref[f, String]

и вы получаете конструктивно равенство
источник

Oℕ

Oleg ℕizhnik in Scala User Group
поэтому одной дырки хватит на всё, и это наиболее универсальный энкодинг, что бы там пропагандисты n дырок не пытались доказать
источник

AT

Aleksei Teryokhin in Scala User Group
Первая заповедь?
источник

Oℕ

Oleg ℕizhnik in Scala User Group
теперь про полисеми.
проблема во всех сортах чего-то поверх обычных фри\фриермонад именно в эмбеддинге только простых эффектов
источник

Oℕ

Oleg ℕizhnik in Scala User Group
т.е. если бы вы пользовались простым Eff от торребора и представили бы новый эффект Read[R]
источник

Oℕ

Oleg ℕizhnik in Scala User Group
это выглядело бы вроде бы хорошо, можно было бы считать, что весь зио эквивалентен чему-то вроде
ZIO[R, E, A] = Eff3[Read[R], Raise[E], Async, A]
источник

Oℕ

Oleg ℕizhnik in Scala User Group
но на самом деле это не совсем так, представьте, что вы написали бы где-то
zio.provideSome(f), с точки зрения рантайма ZIO - это станет функцией, которая один раз трансформирует контекст и успокоится, её эффект во внутренней IO заметен не будет
источник

Oℕ

Oleg ℕizhnik in Scala User Group
поэтому вы можете написать что-то типа
def foo =  readCurrentConfig.flatMap(cfg => action(cfg) *> foo.provideSome(withNewCfg(cfg)))
источник

Oℕ

Oleg ℕizhnik in Scala User Group
но если перевести это на Eff, окажется, что единственный способ сделать provide - это написать handler, который будет обрабатывать все Read на другой Read и функцию преобразования конлтекста,
фактически это будет означать, что на каждую итерацию foo вы добавляете плюс один бесконечно висящий хэндлер, который приводит к квадратичной сложности интерпретации и падению в случае бесконечных процессов
источник

Oℕ

Oleg ℕizhnik in Scala User Group
поэтому были придуманы идеи вроде higher order effects, которые могут включить в качестве эффекта не только конструктор
Read(r => a)
источник

Oℕ

Oleg ℕizhnik in Scala User Group
но и высокоуровневый конструктор
Provide(r: R, F[A, Read[R] & Stack]) extends Effect[A, Stack]
источник

Oℕ

Oleg ℕizhnik in Scala User Group
таким образом Provide будет тоже всего лишь одним слоем вашей фримонады высшего порядка, и вы можете интерпретируя её сделать то же самое, что делает ZIO - просто заменить значение в контексте
источник

Oℕ

Oleg ℕizhnik in Scala User Group
вот эта одна из тех идей, что лежит в основе полисеми
источник