Size: a a a

Scala User Group

2020 August 04

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
хотя кажется, что оно более простое, потому что код на мониторе требует понимания меньшего количества базовых концептов языка
источник

Oℕ

Oleg ℕizhnik in Scala User Group
в результате вы делаете больше матчингов и проверок, которые могли бы не делать
это приводит либо к возрастанию количества тестов, и рантайм ошибок, которые гипотетически не должны возникать,
либо к коду, который делает имплиситные догадке а-ля Option.get
суть в том, что так же, как и в случае Option.get исключить невозможные сценарии с помощью типов
источник

SA

Sergey Alaev in Scala User Group
Так матчить все равно придется? Даже если написать
processAuthReq[A](req: AuthRequest[A]): Result[A], где Result - GADT. Знания A почти наверняка не хватит, чтобы интерпретировать Result
источник

Oℕ

Oleg ℕizhnik in Scala User Group
Sergey Alaev
Конечно, можно еще тайпклассов навертеть над A. Но выглядит сложным, мне не приходит в голову задач, где такое абстрагирование окупилось бы. Возможно, нужно больше практики.
ну например
sealed trait Token

case class SimpleToken(str: String) extends Token
case class JsonToken[A: Encoder](a: A) extends Token

здесь вы получаете возможность определить Encoder[Token] без того, чтобы перегонять данные в JSON, даже если они не будут енкодится
источник

Oℕ

Oleg ℕizhnik in Scala User Group
соответственно, это называется экзистенциальными типами
источник

Oℕ

Oleg ℕizhnik in Scala User Group
а предыдущая форма называется индексированными типами
источник

𝛈µ

𝛈 µ in Scala User Group
Eugene Bosiakov
а что такое ГАДТ?
источник

𝛈µ

𝛈 µ in Scala User Group
прекрасная статья, всё разжёвано
источник

𝛈µ

𝛈 µ in Scala User Group
Теперь доволен?
источник

Oℕ

Oleg ℕizhnik in Scala User Group
да
источник

SA

Sergey Alaev in Scala User Group
Oleg ℕizhnik
sealed trait AuthRequest[A]

case class SimpleAuth(user: String, password: String) extends AuthRequest[(String, String)]

case class BearerAuth(token: String) extends AuthRequest[String]

case class ExternalAuth(provider: String, id: UUID) extends AuthRequest[ExtAuth]

def getAuthReqData[A](req: AuthRequest[A]): IO[A] = req match {
   case SimpleAuth(user, password) => (user, password).pure[IO]
   case BearerAuth(token) => token.pure[IO]
   case ExternalAuth(provider, id) => getExtAuthFor(provider).getAuthData(id)
}
Понял, чем мне не нравится этот пример. мы в GADT закодировали часть внешней логики. Тип ExtAuth не относится к AuthRequest, это часть модели реализации внешней аутентификации.
Похоже на DDD, когда бизнес-логика вносится непосредственно в модель.
источник

Oℕ

Oleg ℕizhnik in Scala User Group
Sergey Alaev
Понял, чем мне не нравится этот пример. мы в GADT закодировали часть внешней логики. Тип ExtAuth не относится к AuthRequest, это часть модели реализации внешней аутентификации.
Похоже на DDD, когда бизнес-логика вносится непосредственно в модель.
относится
источник

Oℕ

Oleg ℕizhnik in Scala User Group
но думаю, что эти рассуждения об отствутвующем коде уже не относятся к мотивации ГАДТ
источник

Oℕ

Oleg ℕizhnik in Scala User Group
стоит упомянуть, что экзистенциальную форму можно заенкодить и другими способами, например
trait JsonToken extends Token{
   type A
  implicit def encoder: Encoder[A]
  val a : A
}

но
использовать её гораздо сложнее
источник

Oℕ

Oleg ℕizhnik in Scala User Group
а вот индексы почти никак иначе не заенкодить в скале, единственный альтернативный способ, который я знаю - это ТФ
источник

Oℕ

Oleg ℕizhnik in Scala User Group
неполноценный способ мог бы выглядеть так
sealed trait AuthRequest[A]

case class SimpleAuth[A](user: String, password: String, ev: A Is (String, String)) extends AuthRequest[A]

case class BearerAuth[A](token: String, ev: A Is String) extends AuthRequest[A]

case class ExternalAuth[A](provider: String, id: UUID, ev: A Is ExtAuth) extends AuthRequest[A]
источник

Oℕ

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