I can modify Map using focus
and index
just fine. Is there a similar functionality in Monocle to update a sequence at given index?
import monocle.syntax.all._
case class C(member: Int)
val map = Map(0 -> C(0), 1 -> C(1))
case class MapContainer(seq: Map[Int, C])
val containedMap = MapContainer(map)
containedMap.focus(_.seq).index(0).replace(C(10)) // works fine
val seq = IndexedSeq(C(0), C(1), C(2))
case class Container(seq: IndexedSeq[C])
val containedSeq = Container(seq)
containedSeq.focus(_.seq).index(0).replace(C(10)) // does not compile
The error is Could not find an instance of Index[IndexedSeq[C],Int,A1]
.
Is such functionality available for Monocle? I was using Quicklens previously and it used at
for both maps and sequences. Unfortunately Quicklens Scala 3 support is not very good at this point, therefore I am exploring alternatives.
CodePudding user response:
From what I see .index
relies on Index
instance which should be available for the type that you want to apply index to.
If you modify your code to this:
val seq = IndexedSeq(C(0), C(1), C(2))
case class Container(seq: List[C]) // List instead of IndexedSeq
val containedSeq = Container(seq.toList)
containedSeq.focus(_.seq).index(0).replace(C(10))
it does compile.
So the issue is lack of instance for IndexedSeq
. Among the build-in instances for standard data types you can see:
implicit def seqIndex[A, S[B] <: SeqOps[B, S, S[B]]]: Index[S[A], Int, A] // this should work
implicit def listIndex[A]: Index[List[A], Int, A]
implicit def lazyListIndex[A]: Index[LazyList[A], Int, A]
implicit def listMapIndex[K, V]: Index[ListMap[K, V], K, V]
implicit def mapIndex[K, V]: Index[Map[K, V], K, V]
implicit def sortedMapIndex[K, V]: Index[SortedMap[K, V], K, V]
implicit val stringIndex: Index[String, Int, Char]
implicit def vectorIndex[A]: Index[Vector[A], Int, A]
but from what I see seqIndex
was added 2 months ago and not released yet (3.1.0 was released a year ago).
So your best bet is to use some specific data structure or implement this implicit yourself.