diff --git a/arrow-optics/src/main/kotlin/arrow/optics/extensions/sequence/each/SequenceKEach.kt b/arrow-optics/src/main/kotlin/arrow/optics/extensions/sequence/each/SequenceKEach.kt new file mode 100644 index 0000000..23622e4 --- /dev/null +++ b/arrow-optics/src/main/kotlin/arrow/optics/extensions/sequence/each/SequenceKEach.kt @@ -0,0 +1,46 @@ +package arrow.optics.extensions.sequence.each + +import arrow.core.SequenceK +import arrow.optics.PTraversal +import arrow.optics.extensions.SequenceKEach + +@JvmName("each") +@Suppress( + "UNCHECKED_CAST", + "USELESS_CAST", + "EXTENSION_SHADOWED_BY_MEMBER", + "UNUSED_PARAMETER" +) +@Deprecated( + "Each is being deprecated. Use the instance for Sequence from Traversal's companion object instead.", + ReplaceWith( + "Traversal.sequence()", + "arrow.optics.Traversal", "arrow.optics.sequence"), + DeprecationLevel.WARNING +) +fun each(): PTraversal, SequenceK, A, A> = + arrow.optics.extensions.sequence.each.Sequence + .each() + .each() as arrow.optics.PTraversal, arrow.core.SequenceK, A, A> + +/** + * cached extension + */ +@PublishedApi() +internal val each_singleton: SequenceKEach = object : SequenceKEach {} + +@Deprecated("Receiver Sequence object is deprecated, and it will be removed in 0.13.") +object Sequence { + @Suppress( + "UNCHECKED_CAST", + "NOTHING_TO_INLINE" + ) + @Deprecated( + "Each is being deprecated. Use the instance for Sequence from Traversal's companion object instead.", + ReplaceWith( + "Traversal.sequence()", + "arrow.optics.Traversal", "arrow.optics.sequence"), + DeprecationLevel.WARNING + ) + inline fun each(): SequenceKEach = each_singleton as + arrow.optics.extensions.SequenceKEach} diff --git a/arrow-optics/src/main/kotlin/arrow/optics/extensions/sequence/filterIndex/SequenceKFilterIndex.kt b/arrow-optics/src/main/kotlin/arrow/optics/extensions/sequence/filterIndex/SequenceKFilterIndex.kt new file mode 100644 index 0000000..08465ce --- /dev/null +++ b/arrow-optics/src/main/kotlin/arrow/optics/extensions/sequence/filterIndex/SequenceKFilterIndex.kt @@ -0,0 +1,49 @@ +package arrow.optics.extensions.sequence.filterIndex + +import arrow.core.SequenceK +import arrow.optics.PTraversal +import arrow.optics.extensions.SequenceKFilterIndex + +@JvmName("filter") +@Suppress( + "UNCHECKED_CAST", + "USELESS_CAST", + "EXTENSION_SHADOWED_BY_MEMBER", + "UNUSED_PARAMETER" +) +@Deprecated( + "arrow.optics.extensions package is being deprecated. Use the exposed function in the instance for Sequence from the companion object of the typeclass instead.", + ReplaceWith( + "FilterIndex.sequence().filter(p)", + "arrow.optics.sequence", "arrow.optics.typeclasses.FilterIndex" + ), + DeprecationLevel.WARNING +) +fun filter(p: Function1): PTraversal, SequenceK, A, A> = + arrow.optics.extensions.sequence.filterIndex.Sequence + .filterIndex() + .filter(p) as arrow.optics.PTraversal, arrow.core.SequenceK, A, A> + +/** + * cached extension + */ +@PublishedApi() +internal val filterIndex_singleton: SequenceKFilterIndex = object : SequenceKFilterIndex + {} + +@Deprecated("Receiver Sequence object is deprecated, and it will be removed in 0.13.") +object Sequence { + @Suppress( + "UNCHECKED_CAST", + "NOTHING_TO_INLINE" + ) + @Deprecated( + "Typeclass instance have been moved to the companion object of the typeclass.", + ReplaceWith( + "FilterIndex.sequence()", + "arrow.optics.sequence", "arrow.optics.typeclasses.FilterIndex" + ), + DeprecationLevel.WARNING + ) + inline fun filterIndex(): SequenceKFilterIndex = filterIndex_singleton as + arrow.optics.extensions.SequenceKFilterIndex} diff --git a/arrow-optics/src/main/kotlin/arrow/optics/extensions/sequence/index/SequenceKIndex.kt b/arrow-optics/src/main/kotlin/arrow/optics/extensions/sequence/index/SequenceKIndex.kt new file mode 100644 index 0000000..b377732 --- /dev/null +++ b/arrow-optics/src/main/kotlin/arrow/optics/extensions/sequence/index/SequenceKIndex.kt @@ -0,0 +1,69 @@ +package arrow.optics.extensions.sequence.index + +import arrow.core.SequenceK +import arrow.optics.PLens +import arrow.optics.POptional +import arrow.optics.extensions.SequenceKIndex + +@JvmName("index") +@Suppress( + "UNCHECKED_CAST", + "USELESS_CAST", + "EXTENSION_SHADOWED_BY_MEMBER", + "UNUSED_PARAMETER" +) +@Deprecated( + "arrow.optics.extensions package is being deprecated. Use the exposed function in the instance for Sequence from the companion object of the typeclass instead.", + ReplaceWith( + "Index.sequence().index(i)", + "arrow.optics.sequence", "arrow.optics.typeclasses.Index" + ), + DeprecationLevel.WARNING +) +fun index(i: Int): POptional, SequenceK, A, A> = + arrow.optics.extensions.sequence.index.Sequence + .index() + .index(i) as arrow.optics.POptional, arrow.core.SequenceK, A, A> + +@JvmName("get") +@Suppress( + "UNCHECKED_CAST", + "USELESS_CAST", + "EXTENSION_SHADOWED_BY_MEMBER", + "UNUSED_PARAMETER" +) +@Deprecated( + "arrow.optics.extensions package is being deprecated, and it will be removed in 0.13.", + ReplaceWith( + "this compose Index.sequence().index(i)", + "arrow.optics.compose", "arrow.optics.sequence", "arrow.optics.typeclasses.Index" + ), + level = DeprecationLevel.WARNING +) +operator fun PLens, SequenceK>.get(i: Int): POptional = + arrow.optics.extensions.sequence.index.Sequence.index().run { + this@get.get(i) as arrow.optics.POptional +} + +/** + * cached extension + */ +@PublishedApi() +internal val index_singleton: SequenceKIndex = object : SequenceKIndex {} + +@Deprecated("Receiver Sequence object is deprecated, and it will be removed in 0.13.") +object Sequence { + @Suppress( + "UNCHECKED_CAST", + "NOTHING_TO_INLINE" + ) + @Deprecated( + "Typeclass instance have been moved to the companion object of the typeclass.", + ReplaceWith( + "Index.sequence()", + "arrow.optics.sequence", "arrow.optics.typeclasses.Index" + ), + DeprecationLevel.WARNING + ) + inline fun index(): SequenceKIndex = index_singleton as + arrow.optics.extensions.SequenceKIndex} diff --git a/arrow-optics/src/main/kotlin/arrow/optics/extensions/sequencek.kt b/arrow-optics/src/main/kotlin/arrow/optics/extensions/sequencek.kt index f1522b5..a3f22ae 100644 --- a/arrow-optics/src/main/kotlin/arrow/optics/extensions/sequencek.kt +++ b/arrow-optics/src/main/kotlin/arrow/optics/extensions/sequencek.kt @@ -6,7 +6,6 @@ import arrow.core.k import arrow.core.left import arrow.core.right import arrow.core.toT -import arrow.extension import arrow.optics.Optional import arrow.optics.POptional import arrow.optics.Traversal @@ -21,6 +20,13 @@ import arrow.typeclasses.Applicative * @receiver [SequenceK.Companion] to make it statically available. * @return [Traversal] with source [SequenceK] and focus in every [A] of the source. */ +@Deprecated( + "SequenceK is being deprecated. Use the instance for Sequence from the companion object of the typeclass.", + ReplaceWith( + "Traversal.sequence()", + "arrow.optics.Traversal", "arrow.optics.sequence"), + DeprecationLevel.WARNING +) fun SequenceK.Companion.traversal(): Traversal, A> = object : Traversal, A> { override fun modifyF(FA: Applicative, s: SequenceK, f: (A) -> Kind): Kind> = s.traverse(FA, f) @@ -29,7 +35,12 @@ fun SequenceK.Companion.traversal(): Traversal, A> = object : T /** * [Each] instance definition for [SequenceK]. */ -@extension +@Deprecated( + "Each is being deprecated. Use the instance for List from Traversal's companion object instead.", + ReplaceWith( + "Traversal.sequence()", + "arrow.optics.Traversal", "arrow.optics.sequence"), + DeprecationLevel.WARNING) interface SequenceKEach : Each, A> { override fun each(): Traversal, A> = SequenceK.traversal() @@ -38,7 +49,14 @@ interface SequenceKEach : Each, A> { /** * [FilterIndex] instance definition for [SequenceK]. */ -@extension +@Deprecated( + "Typeclass interface implementation will not be exposed directly anymore.", + ReplaceWith( + "FilterIndex.sequence()", + "arrow.optics.map", "arrow.optics.typeclasses.FilterIndex" + ), + DeprecationLevel.WARNING +) interface SequenceKFilterIndex : FilterIndex, Int, A> { override fun filter(p: (Int) -> Boolean): Traversal, A> = object : Traversal, A> { override fun modifyF(FA: Applicative, s: SequenceK, f: (A) -> Kind): Kind> = FA.run { @@ -52,7 +70,14 @@ interface SequenceKFilterIndex : FilterIndex, Int, A> { /** * [Index] instance definition for [SequenceK]. */ -@extension +@Deprecated( + "Typeclass interface implementation will not be exposed directly anymore.", + ReplaceWith( + "Index.sequence()", + "arrow.optics.map", "arrow.optics.typeclasses.Index" + ), + DeprecationLevel.WARNING +) interface SequenceKIndex : Index, Int, A> { override fun index(i: Int): Optional, A> = POptional( getOrModify = { it.elementAtOrNull(i)?.right() ?: it.left() }, diff --git a/arrow-optics/src/main/kotlin/arrow/optics/extensions/sequencek/each/SequenceKEach.kt b/arrow-optics/src/main/kotlin/arrow/optics/extensions/sequencek/each/SequenceKEach.kt new file mode 100644 index 0000000..e11b1a9 --- /dev/null +++ b/arrow-optics/src/main/kotlin/arrow/optics/extensions/sequencek/each/SequenceKEach.kt @@ -0,0 +1,44 @@ +package arrow.optics.extensions.sequencek.each + +import arrow.core.SequenceK +import arrow.core.SequenceK.Companion +import arrow.optics.PTraversal +import arrow.optics.extensions.SequenceKEach + +/** + * cached extension + */ +@PublishedApi() +internal val each_singleton: SequenceKEach = object : SequenceKEach {} + +@JvmName("each") +@Suppress( + "UNCHECKED_CAST", + "USELESS_CAST", + "EXTENSION_SHADOWED_BY_MEMBER", + "UNUSED_PARAMETER" +) +@Deprecated( + "Each is being deprecated. Use the instance for Sequence from Traversal's companion object instead.", + ReplaceWith( + "Traversal.sequence()", + "arrow.optics.Traversal", "arrow.optics.sequence"), + DeprecationLevel.WARNING +) +fun each(): PTraversal, SequenceK, A, A> = arrow.core.SequenceK + .each() + .each() as arrow.optics.PTraversal, arrow.core.SequenceK, A, A> + +@Suppress( + "UNCHECKED_CAST", + "NOTHING_TO_INLINE" +) +@Deprecated( + "Each is being deprecated. Use the instance for Sequence from Traversal's companion object instead.", + ReplaceWith( + "Traversal.sequence()", + "arrow.optics.Traversal", "arrow.optics.sequence"), + DeprecationLevel.WARNING +) +inline fun Companion.each(): SequenceKEach = each_singleton as + arrow.optics.extensions.SequenceKEach diff --git a/arrow-optics/src/main/kotlin/arrow/optics/extensions/sequencek/filterIndex/SequenceKFilterIndex.kt b/arrow-optics/src/main/kotlin/arrow/optics/extensions/sequencek/filterIndex/SequenceKFilterIndex.kt new file mode 100644 index 0000000..81407ab --- /dev/null +++ b/arrow-optics/src/main/kotlin/arrow/optics/extensions/sequencek/filterIndex/SequenceKFilterIndex.kt @@ -0,0 +1,48 @@ +package arrow.optics.extensions.sequencek.filterIndex + +import arrow.core.SequenceK +import arrow.core.SequenceK.Companion +import arrow.optics.PTraversal +import arrow.optics.extensions.SequenceKFilterIndex + +/** + * cached extension + */ +@PublishedApi() +internal val filterIndex_singleton: SequenceKFilterIndex = object : SequenceKFilterIndex + {} + +@JvmName("filter") +@Suppress( + "UNCHECKED_CAST", + "USELESS_CAST", + "EXTENSION_SHADOWED_BY_MEMBER", + "UNUSED_PARAMETER" +) +@Deprecated( + "arrow.optics.extensions package is being deprecated. Use the exposed function in the instance for Sequence from the companion object of the typeclass instead.", + ReplaceWith( + "FilterIndex.sequence().filter(p)", + "arrow.optics.sequence", "arrow.optics.typeclasses.FilterIndex" + ), + DeprecationLevel.WARNING +) +fun filter(p: Function1): PTraversal, SequenceK, A, A> = + arrow.core.SequenceK + .filterIndex() + .filter(p) as arrow.optics.PTraversal, arrow.core.SequenceK, A, A> + +@Suppress( + "UNCHECKED_CAST", + "NOTHING_TO_INLINE" +) +@Deprecated( + "SequenceK is being deprecated. Use the instance for Sequence from the companion object of the typeclass.", + ReplaceWith( + "FilterIndex.sequence()", + "arrow.optics.sequence", "arrow.optics.typeclasses.FilterIndex" + ), + DeprecationLevel.WARNING +) +inline fun Companion.filterIndex(): SequenceKFilterIndex = filterIndex_singleton as + arrow.optics.extensions.SequenceKFilterIndex diff --git a/arrow-optics/src/main/kotlin/arrow/optics/extensions/sequencek/index/SequenceKIndex.kt b/arrow-optics/src/main/kotlin/arrow/optics/extensions/sequencek/index/SequenceKIndex.kt new file mode 100644 index 0000000..57408c4 --- /dev/null +++ b/arrow-optics/src/main/kotlin/arrow/optics/extensions/sequencek/index/SequenceKIndex.kt @@ -0,0 +1,67 @@ +package arrow.optics.extensions.sequencek.index + +import arrow.core.SequenceK +import arrow.core.SequenceK.Companion +import arrow.optics.PLens +import arrow.optics.POptional +import arrow.optics.extensions.SequenceKIndex + +/** + * cached extension + */ +@PublishedApi() +internal val index_singleton: SequenceKIndex = object : SequenceKIndex {} + +@JvmName("index") +@Suppress( + "UNCHECKED_CAST", + "USELESS_CAST", + "EXTENSION_SHADOWED_BY_MEMBER", + "UNUSED_PARAMETER" +) +@Deprecated( + "arrow.optics.extensions package is being deprecated. Use the exposed function in the instance for Sequence from the companion object of the typeclass instead.", + ReplaceWith( + "Index.sequence().index(i)", + "arrow.optics.sequence", "arrow.optics.typeclasses.Index" + ), + DeprecationLevel.WARNING +) +fun index(i: Int): POptional, SequenceK, A, A> = arrow.core.SequenceK + .index() + .index(i) as arrow.optics.POptional, arrow.core.SequenceK, A, A> + +@JvmName("get") +@Suppress( + "UNCHECKED_CAST", + "USELESS_CAST", + "EXTENSION_SHADOWED_BY_MEMBER", + "UNUSED_PARAMETER" +) +@Deprecated( + "arrow.optics.extensions package is being deprecated, and it will be removed in 0.13.", + ReplaceWith( + "this compose Index.sequence().index(i)", + "arrow.optics.compose", "arrow.optics.sequence", "arrow.optics.typeclasses.Index" + ), + level = DeprecationLevel.WARNING +) +operator fun PLens, SequenceK>.get(i: Int): POptional = + arrow.core.SequenceK.index().run { + this@get.get(i) as arrow.optics.POptional +} + +@Suppress( + "UNCHECKED_CAST", + "NOTHING_TO_INLINE" +) +@Deprecated( + "SequenceK is being deprecated. Use the instance for Sequence from the companion object of the typeclass.", + ReplaceWith( + "Index.sequence()", + "arrow.optics.sequence", "arrow.optics.typeclasses.Index" + ), + DeprecationLevel.WARNING +) +inline fun Companion.index(): SequenceKIndex = index_singleton as + arrow.optics.extensions.SequenceKIndex diff --git a/arrow-optics/src/main/kotlin/arrow/optics/std/sequence.kt b/arrow-optics/src/main/kotlin/arrow/optics/std/sequence.kt new file mode 100644 index 0000000..e879e0e --- /dev/null +++ b/arrow-optics/src/main/kotlin/arrow/optics/std/sequence.kt @@ -0,0 +1,33 @@ +package arrow.optics + +import arrow.Kind +import arrow.core.k +import arrow.core.left +import arrow.core.right +import arrow.core.toT +import arrow.optics.typeclasses.FilterIndex +import arrow.optics.typeclasses.Index +import arrow.typeclasses.Applicative + +fun FilterIndex.Companion.sequence(): FilterIndex, Int, A> = FilterIndex { p -> + object : Traversal, A> { + override fun modifyF(FA: Applicative, s: Sequence, f: (A) -> Kind): Kind> = + FA.run { + s.mapIndexed { index, a -> a toT index }.k().traverse(FA) { (a, j) -> if (p(j)) f(a) else just(a) + } + } + } +} + +fun Index.Companion.sequence(): Index, Int, A> = Index { i -> + POptional( + getOrModify = { it.elementAtOrNull(i)?.right() ?: it.left() }, + set = { s, a -> s.mapIndexed { index, aa -> if (index == i) a else aa } } + ) +} + +fun PTraversal.Companion.sequence(): Traversal, A> = + object : Traversal, A> { + override fun modifyF(FA: Applicative, s: Sequence, f: (A) -> Kind): Kind> = + FA.run { s.k().traverse(FA, f) } + } diff --git a/arrow-optics/src/test/kotlin/arrow/optics/instances/SequenceInstanceTest.kt b/arrow-optics/src/test/kotlin/arrow/optics/instances/SequenceInstanceTest.kt new file mode 100644 index 0000000..331173e --- /dev/null +++ b/arrow-optics/src/test/kotlin/arrow/optics/instances/SequenceInstanceTest.kt @@ -0,0 +1,66 @@ +package arrow.optics.instances + +import arrow.core.Option +import arrow.core.SequenceK +import arrow.core.extensions.eq +import arrow.core.extensions.option.eq.eq +import arrow.core.extensions.sequencek.eq.eq +import arrow.core.list +import arrow.core.test.UnitSpec +import arrow.core.test.generators.functionAToB +import arrow.optics.Traversal +import arrow.optics.sequence +import arrow.optics.test.laws.OptionalLaws +import arrow.optics.test.laws.TraversalLaws +import arrow.optics.typeclasses.FilterIndex +import arrow.optics.typeclasses.Index +import arrow.typeclasses.Eq +import io.kotlintest.properties.Gen + +class SequenceInstanceTest : UnitSpec() { + + private fun Gen.Companion.sequence(genA: Gen): Gen> = list(genA).map { it.asSequence() } + + private fun sequenceEq(eqA: Eq): Eq> = object : Eq> { + override fun Sequence.eqv(b: Sequence): Boolean = + SequenceK.eq(eqA).run { SequenceK(this@eqv).eqv(SequenceK(b)) } + } + + init { + + testLaws( + TraversalLaws.laws( + traversal = Traversal.sequence(), + aGen = Gen.sequence(Gen.string()), + bGen = Gen.string(), + funcGen = Gen.functionAToB(Gen.string()), + EQA = sequenceEq(String.eq()), + EQOptionB = Option.eq(String.eq()), + EQListB = Eq.list(String.eq()) + ) + ) + + testLaws( + TraversalLaws.laws( + traversal = FilterIndex.sequence().filter { true }, + aGen = Gen.sequence(Gen.string()), + bGen = Gen.string(), + funcGen = Gen.functionAToB(Gen.string()), + EQA = sequenceEq(String.eq()), + EQListB = Eq.list(String.eq()), + EQOptionB = Option.eq(String.eq()) + ) + ) + + testLaws( + OptionalLaws.laws( + optionalGen = Gen.int().map { Index.sequence().index(it) }, + aGen = Gen.sequence(Gen.string()), + bGen = Gen.string(), + funcGen = Gen.functionAToB(Gen.string()), + EQOptionB = Option.eq(String.eq()), + EQA = sequenceEq(String.eq()) + ) + ) + } +}