Size: a a a

Scala User Group

2020 November 30

VS

Vladimir Sapronov in Scala User Group
Как отвязать декодер енамов от конретного типа енама - вот что не понятно.
trait завести - это я могу
источник

λ

λoλcat in Scala User Group
implicit decoder: String => T
Это не то
источник

M

Mikhail in Scala User Group
Vladimir Sapronov
Не понял? Это же ровно то, что у меня в скасте и написано, или я не вижу в упор чего-то?
И да, и нет. Но ничего, это придет позже. И твой вариант может работать https://scastie.scala-lang.org/rudogma/vcskAh1FSFiVa1UQZjw0UQ/2
источник

KS

Kirill Shelopugin in Scala User Group
Vladimir Sapronov
Приветствую уважаемые!

Имею вопрос-предположение и нескем обмозговать...

Делаю чтто-то вроде "попарсим значения всяких разных типы типобезопасно". Т.е. хочется, чтобы была ф-ция read[T](s: String): T которая парсит из строки значение типа T. Т.к. нужна типобезопасность, то добавляю имплиситный декодер: read[T](s: String)(implicit decoder: String => T): T ну и понятно, если декодер определен для T то все хорошо.

Теперь проблема кооторую я имею касается enumreatum енамов. Вот такой декодер я соорудить смог:
def decodeStringEnum[T <: StringEnumEntry: StringEnum](s: String): T =
   implicitly[StringEnum[T]].withValue(s)


Но не смог его (1) имплиситно прокинуть (2) использовать его не специфицируя T. Смог только вот так:
va
l theChoice = TheReader.read[Choice]("SECOND")(StringCodecs.decodeStringEnum[Choice])
// Choice - это enumeratum енам

Вот здесь сделал пример, для наглядности с Int и с енамом, Int - это то как хочется для енамов....
https://scastie.scala-lang.org/5lDY5EmNQ1OuJ43iJ1UiwA
1) имплиситно прокинуть можно вот так: implicit val decodeChoice: (String => Choice) = StringCodecs.decodeStringEnum[Choice], там же рядом с decodeInt
2) Не специфицировать Choice не получится - компилятор не может угадать, какой тип ты хотел получить в итоге. Указать придется либо у val либо при вызове метода
Но вообще Михаил прав - лучше сделать TheReader тайпклассом. У тебя написано не то же самое - ты определил свой read, который требует какую-то функцию, а не инстанс тайпкласса.
источник

VS

Vladimir Sapronov in Scala User Group
Воооот, OK решили вопрос #1 - он был легкий, но: "(2) использовать его не специфицируя T"
Там специфицирован конретный T - Choice. Т.е. на каждый отдельно взятый енам надо создать ридер/декодер - как ни назови....
источник

M

Mikhail in Scala User Group
Vladimir Sapronov
Как отвязать декодер енамов от конретного типа енама - вот что не понятно.
trait завести - это я могу
extends Enum не порождает какого-либо компаньона с имплиситом внутри. Т.е. тебе все равно для твоего инстанса надо в любом виде его явно определить самому
источник

λ

λoλcat in Scala User Group
Kirill Shelopugin
1) имплиситно прокинуть можно вот так: implicit val decodeChoice: (String => Choice) = StringCodecs.decodeStringEnum[Choice], там же рядом с decodeInt
2) Не специфицировать Choice не получится - компилятор не может угадать, какой тип ты хотел получить в итоге. Указать придется либо у val либо при вызове метода
Но вообще Михаил прав - лучше сделать TheReader тайпклассом. У тебя написано не то же самое - ты определил свой read, который требует какую-то функцию, а не инстанс тайпкласса.
Зачем ты плохому учишь?
источник

KS

Kirill Shelopugin in Scala User Group
λoλcat
Зачем ты плохому учишь?
Чему?
источник

λ

λoλcat in Scala User Group
Имплисным функциям вместо тайпкласса
источник

KS

Kirill Shelopugin in Scala User Group
Ну, я сначала ответил на вопросы человека. А потом уже сказал, что тайпклассом лучше.
источник

M

Mikhail in Scala User Group
Mikhail
extends Enum не порождает какого-либо компаньона с имплиситом внутри. Т.е. тебе все равно для твоего инстанса надо в любом виде его явно определить самому
Или порождает? Надо глянуть
источник

VS

Vladimir Sapronov in Scala User Group
Kirill Shelopugin
1) имплиситно прокинуть можно вот так: implicit val decodeChoice: (String => Choice) = StringCodecs.decodeStringEnum[Choice], там же рядом с decodeInt
2) Не специфицировать Choice не получится - компилятор не может угадать, какой тип ты хотел получить в итоге. Указать придется либо у val либо при вызове метода
Но вообще Михаил прав - лучше сделать TheReader тайпклассом. У тебя написано не то же самое - ты определил свой read, который требует какую-то функцию, а не инстанс тайпкласса.
Отдельный вопрос: почему лучше сделать reader тайпклассом. Я не спорю, но это не очевидно, чем это лучше? Но это не главный вопрос.... Я в принципе понимаю и так и так.

Т.е. мое опасение, что не специфицировать тип каждого енама не прокатит - это я правильно боялся?
источник

VS

Vladimir Sapronov in Scala User Group
λoλcat
Имплисным функциям вместо тайпкласса
Почему это плохо? Можно послать меня почитать статейку там - не обязательно разжевывать.
источник

KS

Kirill Shelopugin in Scala User Group
Vladimir Sapronov
Отдельный вопрос: почему лучше сделать reader тайпклассом. Я не спорю, но это не очевидно, чем это лучше? Но это не главный вопрос.... Я в принципе понимаю и так и так.

Т.е. мое опасение, что не специфицировать тип каждого енама не прокатит - это я правильно боялся?
Я не понял, что подразумевалось под "не специфицировать тип каждого енама".
источник

λ

λoλcat in Scala User Group
Имплиситные функции это конверсии
источник

λ

λoλcat in Scala User Group
Их специально в скале3 сделали сложнее
источник

λ

λoλcat in Scala User Group
Чтобы люди реже использовали
источник

VS

Vladimir Sapronov in Scala User Group
Kirill Shelopugin
Я не понял, что подразумевалось под "не специфицировать тип каждого енама".
Ну как бы нельзя сделать все енамы декодируемыми из строки одной - функцией. Представь, что у меня 30 енамов....
источник

KS

Kirill Shelopugin in Scala User Group
Функции это конвертирование, тайпклассы - специальный полиморфизм.
источник

KS

Kirill Shelopugin in Scala User Group
Vladimir Sapronov
Ну как бы нельзя сделать все енамы декодируемыми из строки одной - функцией. Представь, что у меня 30 енамов....
Почему нельзя-то? Вот ты же сделал, напиши рядом второй энам и из строки в него парси той же функцией read
источник