Skip to content

Commit

Permalink
Merge pull request #91 from OndrejSpanel/seq-index
Browse files Browse the repository at this point in the history
Scala 3 support for Seq / IndexedSeq
  • Loading branch information
adamw authored Apr 28, 2022
2 parents 4f56d6f + 1ff6651 commit 93581d8
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 13 deletions.
23 changes: 10 additions & 13 deletions quicklens/src/main/scala-3/com/softwaremill/quicklens/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,8 @@ package object quicklens {
}

object QuicklensFunctor {
given QuicklensFunctor[List] with {
def map[A, B](fa: List[A], f: A => B): List[B] = fa.map(f)
}

given QuicklensFunctor[Seq] with {
def map[A, B](fa: Seq[A], f: A => B): Seq[B] = fa.map(f)
given [S <: ([V] =>> Seq[V])]: QuicklensFunctor[S] with {
def map[A, B](fa: S[A], f: A => B): S[B] = fa.map(f).asInstanceOf[S[B]]
}

given QuicklensFunctor[Option] with {
Expand All @@ -163,14 +159,15 @@ package object quicklens {
}

object QuicklensIndexedFunctor {
given QuicklensIndexedFunctor[List, Int] with {
def at[A](fa: List[A], f: A => A, idx: Int): List[A] =
fa.updated(idx, f(fa(idx)))
def atOrElse[A](fa: List[A], f: A => A, idx: Int, default: => A): List[A] =
fa.updated(idx, f(fa.applyOrElse(idx, Function.const(default))))
def index[A](fa: List[A], f: A => A, idx: Int): List[A] =
if fa.isDefinedAt(idx) then fa.updated(idx, f(fa(idx))) else fa
given [S <: ([V] =>> Seq[V])]: QuicklensIndexedFunctor[S, Int] with {
def at[A](fa: S[A], f: A => A, idx: Int): S[A] =
fa.updated(idx, f(fa(idx))).asInstanceOf[S[A]]
def atOrElse[A](fa: S[A], f: A => A, idx: Int, default: => A): S[A] =
fa.updated(idx, f(fa.applyOrElse(idx, Function.const(default)))).asInstanceOf[S[A]]
def index[A](fa: S[A], f: A => A, idx: Int): S[A] =
if fa.isDefinedAt(idx) then fa.updated(idx, f(fa(idx))).asInstanceOf[S[A]] else fa
}

given [K, M <: ([V] =>> Map[K, V])]: QuicklensIndexedFunctor[M, K] with {
def at[A](fa: M[A], f: A => A, idx: K): M[A] =
fa.updated(idx, f(fa(idx))).asInstanceOf[M[A]]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.softwaremill.quicklens

import com.softwaremill.quicklens.TestData._
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

class ModifyIndexedSeqIndexTest extends AnyFlatSpec with Matchers {

it should "modify a non-nested indexed seq with case class item" in {
modify(is1)(_.index(2).a4.a5.name).using(duplicate) should be(l1at2dup)
modify(is1)(_.index(2))
.using(a3 => modify(a3)(_.a4.a5.name).using(duplicate)) should be(l1at2dup)
}

it should "modify a nested indexed seq using index" in {
modify(iss1)(_.index(2).index(1).name).using(duplicate) should be(ll1at2at1dup)
}

it should "modify a nested indexed seq using index and each" in {
modify(iss1)(_.index(2).each.name).using(duplicate) should be(ll1at2eachdup)
modify(iss1)(_.each.index(1).name).using(duplicate) should be(ll1eachat1dup)
}

it should "not modify if given index does not exist" in {
modify(is1)(_.index(10).a4.a5.name).using(duplicate) should be(l1)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.softwaremill.quicklens

import com.softwaremill.quicklens.TestData._
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

class ModifySeqIndexTest extends AnyFlatSpec with Matchers {

it should "modify a non-nested seq with case class item" in {
modify(s1)(_.index(2).a4.a5.name).using(duplicate) should be(l1at2dup)
modify(s1)(_.index(2))
.using(a3 => modify(a3)(_.a4.a5.name).using(duplicate)) should be(l1at2dup)
}

it should "modify a nested seq using index" in {
modify(ss1)(_.index(2).index(1).name).using(duplicate) should be(ll1at2at1dup)
}

it should "modify a nested seq using index and each" in {
modify(ss1)(_.index(2).each.name).using(duplicate) should be(ll1at2eachdup)
modify(ss1)(_.each.index(1).name).using(duplicate) should be(ll1eachat1dup)
}

it should "not modify if given index does not exist" in {
modify(s1)(_.index(10).a4.a5.name).using(duplicate) should be(l1)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ object TestData {
val ll1at2eachdup = List(List(A5("d1"), A5("d2")), List(A5("d3"), A5("d4"), A5("d5")), List(A5("d6d6"), A5("d7d7")))
val ll1eachat1dup = List(List(A5("d1"), A5("d2d2")), List(A5("d3"), A5("d4d4"), A5("d5")), List(A5("d6"), A5("d7d7")))


val s1: Seq[A3] = l1
val ss1: Seq[Seq[A5]] = ll1

val is1 = l1.toIndexedSeq
val iss1 = ss1.map(_.toIndexedSeq).toIndexedSeq

case class M2(m3: Map[String, A4])

val m1 = Map("K1" -> A4(A5("d1")), "K2" -> A4(A5("d2")), "K3" -> A4(A5("d3")))
Expand Down

0 comments on commit 93581d8

Please sign in to comment.