Tuples transformations
This is mini project to transform tuple and its types.
It's Scala 3 only.
To install
libraryDependencies += "io.github.mercurievv.minuscles" % "tuples-transformers" % "0.2.1"
Use import
import io.github.mercurievv.minuscles.tuples.transformers.all.*
Let's create some input data:
val input: ((Int, Long), (String, (Boolean, Double, Char), (Float, Byte))) = ((1, 2L), ("3", (true, 0.5D, "6".charAt(0)), (0.7F, 0x8)))
// input: Tuple2[Tuple2[Int, Long], Tuple3[String, Tuple3[Boolean, Double, Char], Tuple2[Float, Byte]]] = (
// (1, 2L),
// ("3", (true, 0.5, '6'), (0.7F, 8))
// )
Now we will do some transformations:
Flattening, Nesting
val flatten: (Int, Long, String, Boolean, Double, Char, Float, Byte) = input.toFlatten
// flatten: Tuple8[Int, Long, String, Boolean, Double, Char, Float, Byte] = (
// 1,
// 2L,
// "3",
// true,
// 0.5,
// '6',
// 0.7F,
// 8
// )
val flattenToNested: (Int, (Long, (String, (Boolean, (Double, (Char, (Float, Byte))))))) = flatToNestedR(flatten)
// flattenToNested: Tuple2[Int, Tuple2[Long, Tuple2[String, Tuple2[Boolean, Tuple2[Double, Tuple2[Char, Tuple2[Float, Byte]]]]]]] = (
// 1,
// (2L, ("3", (true, (0.5, ('6', (0.7F, 8))))))
// )
//flatToNested method works correctly only with flattened tuples, but in such cases it should save some CPU
val nested: (Int, (Long, (String, (Boolean, (Double, (Char, (Float, Byte))))))) = input.toNestedR
// nested: Tuple2[Int, Tuple2[Long, Tuple2[String, Tuple2[Boolean, Tuple2[Double, Tuple2[Char, Tuple2[Float, Byte]]]]]]] = (
// 1,
// (2L, ("3", (true, (0.5, ('6', (0.7F, 8))))))
// )
Two Elements Swap
Swapping 2 elements of tuple.
val swapped: (Int, Boolean, String, Long, Double, Char, Float, Byte) = flatten.swap(2, 4)
// swapped: Tuple8[Int, Boolean, String, Long, Double, Char, Float, Byte] = (
// 1,
// true,
// "3",
// 2L,
// 0.5,
// '6',
// 0.7F,
// 8
// )
Unflatten
Reconstruct the original nested structure from a flat tuple.
val fromFlattenV: ((Int, Long), (String, (Boolean, Double, Char), (Float, Byte))) = fromFlatten[((Int, Long), (String, (Boolean, Double, Char), (Float, Byte)))](flatten)
// fromFlattenV: Tuple2[Tuple2[Int, Long], Tuple3[String, Tuple3[Boolean, Double, Char], Tuple2[Float, Byte]]] = (
// (1, 2L),
// ("3", (true, 0.5, '6'), (0.7F, 8))
// )
From Nested-Right
Reconstruct the original structure from a nested-right tuple.
val fromNested: ((Int, Long), (String, (Boolean, Double, Char), (Float, Byte))) = fromNestedR[((Int, Long), (String, (Boolean, Double, Char), (Float, Byte)))](nested)
// fromNested: Tuple2[Tuple2[Int, Long], Tuple3[String, Tuple3[Boolean, Double, Char], Tuple2[Float, Byte]]] = (
// (1, 2L),
// ("3", (true, 0.5, '6'), (0.7F, 8))
// )
Reorder by Type
Reorder tuple elements by specifying the desired output type. All element types must be unique.
val t = ("hello", 42, 3.14)
// t: Tuple3[String, Int, Double] = ("hello", 42, 3.14)
val reordered: (Int, Double, String) = reorder[(String, Int, Double), (Int, Double, String)](t)
// reordered: Tuple3[Int, Double, String] = (42, 3.14, "hello")
val reorderedExt: (Int, Double, String) = t.reorderTo[(Int, Double, String)]
// reorderedExt: Tuple3[Int, Double, String] = (42, 3.14, "hello")
Duplicate types in the source are rejected at compile time:
val bad: (String, Int, String) = ("a", 1, "b")
reorder[(String, Int, String), (Int, String)](bad)
// error:
// No given instance of type io.github.mercurievv.minuscles.tuples.transformers.all.IsDistinct[(String, Int,
// String)] was found for parameter d of method reorder in object all.
// I found:
//
// io.github.mercurievv.minuscles.tuples.transformers.all.IsDistinct.consDistinct[
// String, (Int, String)](
// /* missing */
// summon[
// scala.util.NotGiven[
// io.github.mercurievv.minuscles.tuples.transformers.all.TupleIndex[
// (Int, String), String]
// ]
// ]
// ,
// ???)
//
// But no implicit values were found that match type scala.util.NotGiven[
// io.github.mercurievv.minuscles.tuples.transformers.all.TupleIndex[
// (Int, String), String]
// ].
// reorder[(String, Int, String), (Int, String)](bad)
// ^
Distinct types constraint
IsDistinct[T] is a typeclass witness that all element types in T are unique.
It is used automatically by reorder/reorderTo, but can also be used as a constraint in your own code.
Require a distinct tuple at a call site:
val distinct = t.requireDistinct // compiles — (String, Int, Double) has unique types
// distinct: Tuple3[String, Int, Double] = ("hello", 42, 3.14)
val bad2: (String, Int, String) = ("a", 1, "b")
bad2.requireDistinct
// error:
// value requireDistinct is not a member of (String, Int, String).
// An extension method was tried, but could not be fully constructed:
//
// io.github.mercurievv.minuscles.tuples.transformers.all.requireDistinct[
// (String, Int, String)](repl.MdocSession.MdocApp.bad2)(
// io.github.mercurievv.minuscles.tuples.transformers.all.IsDistinct.consDistinct
// [String, (Int, String)](
// /* missing */
// summon[
// scala.util.NotGiven[
// io.github.mercurievv.minuscles.tuples.transformers.all.TupleIndex[
// (Int, String), String]
// ]
// ]
// ,
// ???)
// )
//
// failed with:
//
// No given instance of type io.github.mercurievv.minuscles.tuples.transformers.all.IsDistinct[
// (String, Int, String)] was found for parameter x$2 of method requireDistinct in object all.
// I found:
//
// io.github.mercurievv.minuscles.tuples.transformers.all.IsDistinct.consDistinct[
// String, (Int, String)](
// /* missing */
// summon[
// scala.util.NotGiven[
// io.github.mercurievv.minuscles.tuples.transformers.all.TupleIndex[
// (Int, String), String]
// ]
// ]
// ,
// ???)
//
// But no implicit values were found that match type scala.util.NotGiven[
// io.github.mercurievv.minuscles.tuples.transformers.all.TupleIndex[
// (Int, String), String]
// ].
// bad2.requireDistinct
// ^^^^^^^^^^^^^^^^^^^^
Use as a constraint in your own function:
def processDistinct[T <: Tuple](t: T)(using IsDistinct[T]): String = t.toString