Here’s what I did for better code organization.
├── Main.scala
└── myutils
├── BaseEncoder.scala
├── CaseClass2CSV.scala
├── FieldEncoder.scala
├── RowEncoder.scala
└── TupleEncoder.scala
Each file is as follows.
BaseEncoder.scala
package myutils
package encoder
package instances
given FieldEncoder[Int] with
def encodeField(x: Int) = x.toString
given FieldEncoder[Boolean] with
def encodeField(x: Boolean) = if x then "true" else "false"
given FieldEncoder[String] with
def encodeField(x: String) = x
CaseClass2CSV.scala
package myutils
package encoder
package instances
package func
def tupleToCsv[X <: Tuple: RowEncoder](tuple: X): List[String] =
summon[RowEncoder[X]].encodeRow(tuple)
FieldEncoder.scala
package myutils
package encoder
trait FieldEncoder[A]:
def encodeField(a: A): String
RowEncoder.scala
package myutils
package encoder
type Row = List[String]
trait RowEncoder[A]:
def encodeRow(a: A): Row
TupleEncoder.scala
package myutils
package encoder
package instances
given RowEncoder[EmptyTuple] with
def encodeRow(empty: EmptyTuple) =
List.empty
given [H: FieldEncoder, T <: Tuple: RowEncoder]: RowEncoder[H *: T] with
def encodeRow(tuple: H *: T) =
summon[FieldEncoder[H]].encodeField(tuple.head) :: summon[RowEncoder[T]]
.encodeRow(tuple.tail)
I ran the following main and it works nicely
import myutils.encoder.instances.func.tupleToCsv
import myutils.encoder.instances.given
@main def hello: Unit = {
println(tupleToCsv((42, true, "Hello")))
}
Any suggestion to make it better is welcome! I’m very new to scala and it would be lovely to have some advice from experienced scala users.