Как обновить карту с помощью монокля
Я хотел бы попробовать библиотеку Monocle. Но я не мог найти справочные ресурсы для базового синтаксиса.
Короче мне нужна оптика Map[K,V] -> A
с оптикой V -> A
Как я могу определить это?
Предположим, у меня есть немного
import monocle.macros.GenLens
case class DirState(opened: Boolean)
object DirState {
val opened = GenLens[DirState](_.opened)
}
type Path = List[String]
type StateStore = Map[Path, DirState]
Далее я встречаю место, где мне нужно просто StateStore => StateStore
я импортирую
import monocle._
import monocle.std._
import monocle.syntax._
import monocle.function._
И пытается определить сначала:
def setOpened(path: Path): StateStore => StateStore =
at(path) composeLens DirState.opened set true
Как добраться
неоднозначные неявные значения: оба метода
atMap
вtrait MapInstances
типа[K, V]=> monocle.function.At[Map[K,V],K,V]
и методatSet
вtrait SetInstances
типа[A]=> monocle.function.At[Set[A],A,Unit]
соответствует ожидаемому типуmonocle.function.At[S,Path,A]
Пытаюсь изменить мое определение на
def setOpened(path: Path): StateStore => StateStore =
index(path) composeLens DirState.opened set true
Получение сейчас:
несоответствие типов; найденный:
monocle.function.Index[Map[Path,Nothing],Path,Nothing]
(который расширяется до)monocle.function.Index[Map[List[String],Nothing],List[String],Nothing]
требуется:monocle.function.Index[Map[Path,Nothing],Path,A]
(который расширяется до)monocle.function.Index[Map[List[String],Nothing],List[String],A]
Замечания:
Nothing <: A
, ноtrait Index
инвариантен по типуA
, Вы можете определитьA
как+A
вместо. (SLS 4.5)
2 ответа
import monocle.function.index._
import monocle.std.map._
import monocle.syntax._
def setOpened(path: Path)(s: StateStore): StateStore =
(s applyOptional index(path) composeLens DirState.opened).set(true)
давайте посмотрим на тип index
def index[S, I, A](i: I)(implicit ev: Index[S, I, A]): Optional[S, A] =
ev.index(i)
trait Index[S, I, A] {
def index(i: I): Optional[S, A]
}
Так index
вызвать экземпляр класса типа Index
типа Index[S, I, A]
, Это позволяет использовать index
за Map
, List
, Vector
и так далее.
Проблема в том, что компилятору scala нужно определить 3 типа: S
, I
а также A
на сайте вызова index
, I
это просто, это тип параметра, который вы передаете index
, Тем не мение,S
а также A
знают только когда ты звонишь set
,
apply
Синтаксис был создан, чтобы вести вывод типа для такого сценария, в основном applyOptional
захваты S
который Map[Path, DirState]
, Это дает достаточно информации для вывода компилятора A =:= DirState
,
Множество примеров того, как это сделать, и множество других полезных советов доступны в репозитории Monocle:
https://github.com/julien-truffaut/Monocle/blob/master/example/src/test/scala/monocle/function/
Более конкретно для этого сценария: https://github.com/julien-truffaut/Monocle/blob/master/example/src/test/scala/monocle/function/FilterIndexExample.scala