RE: https://witter.cz/@matejcerny/116777155771993798
to reduce the extra 2MB that Scaladoc adds, I've created an sbt plugin sbt-salad-days
https://eed3si9n.com/reducing-scaladoc-file-size-with-sbt-salad-days/ #Scala
RE: https://witter.cz/@matejcerny/116777155771993798
to reduce the extra 2MB that Scaladoc adds, I've created an sbt plugin sbt-salad-days
https://eed3si9n.com/reducing-scaladoc-file-size-with-sbt-salad-days/ #Scala
There was no e-mail, and I learned it by accident, but I feel all #Scala OSS devs should learn ASAP: Maven is introducing publishing limits. We most likely will have to apply for exemption:
- https://www.sonatype.com/blog/open-publishing-commercial-scale
- https://central.sonatype.org/publish/maven-central-publishing-limits
🛠️ sbt 2.0.0 is released
sbt 2.0 is a new major series of sbt, based on Scala 3 constructs and Bazel-compatible cache system. many thanks to Scala Center, Anatolii Kmetiuk (new maintainer), Adrien Piquerez (alumni), and other volunteers like Kenji Yoshida
https://eed3si9n.com/sbt-2.0.0 #Scala
I have written up a more detailed post about linear regression with #probula using grid approximation. The post focuses on:
probula (which is an internal DSL embedded in Scala 3)probulaEnjoy!
https://wasowski.dukla.ch/posts/2606-grid-approximation-with-probula/
#ProbabilisticProgramming #Bayesian #Inference #DataAnalysis #Scala #Scala3 #keep
Let me share an update on probula, my small purely-functional Bayesian inference library written in Scala 3. The primary goal for this write-up is to force myself (and you) to think about testing of probabilistic models, of inference algorithms, and the languages or APIs in which they are formulated. Arguably, this is a very modest start. But more is on the way! I would like to start with the first inference scheme you encounter, when reading McElreath’s Statistical Rethinking. Grid approximation (as this is the scheme we speak about) is by far the least efficient of the methods discussed in the book, but it remains useful as a testing baseline. Its simplicity and determinism let it serve as ground truth and oracle for other, more complex inference methods.
@bthuillier thanks for the write up. Here is the code as a scastie: https://scastie.scala-lang.org/inTw8qeaSSOVYAilzEZEPQ
Changes: Moved the many witnesses into the `Debuggable` companion object. Also dropped an unused explicit parameter in `productDebuggable` line 39
Suggestion (please feel free to ignore it): don't know how ephemeral the scastie is.. perhaps you'd like to hoist it as a gist and share it in your writeup
Edit: updated the link to the version that is being talked about

//> using scala 3.8.3 //> using options -feature -language:strictEquality -Wunused:all -Wsafe-init -deprecation import scala.compiletime.* import scala.deriving.Mirror import scala.language.implicitConversions trait Debuggable[T]: extension (x: T) def debug: String object Debuggable: inline def derived[T](using m: Mirror.Of[T]): Debuggable[T] = val instances = summonAll[m.MirroredElemTypes] val labels = labelsOf[m.MirroredElemLabels] val typeName = constValue[m.MirroredLabel] inline m match case _: Mirror.ProductOf[T] => productDebuggable(typeName, labels, instances) case s: Mirror.SumOf[T] => sumDebuggable(instances, s) private inline def summonAll[T <: Tuple]: List[Debuggable[?]] = inline erasedValue[T] match case _: EmptyTuple => Nil case _: (head *: tail) => deriveOrSummon[head] :: summonAll[tail] private inline def labelsOf[T <: Tuple]: List[String] = inline erasedValue[T] match case _: EmptyTuple => Nil case _: (head *: tail) => constValue[head].asInstanceOf[String] :: labelsOf[tail] private inline def deriveOrSummon[T]: Debuggable[T] = summonFrom { case d: Debuggable[T] => d case m: Mirror.Of[T] => derived[T](using m) } private def productDebuggable[T]( typeName: String, labels: List[String], instances: List[Debuggable[?]] ): Debuggable[T] = new Debuggable[T]: extension (x: T) def debug: String = val fields = x.asInstanceOf[Product].productIterator.toList val parts = fields.lazyZip(instances).lazyZip(labels).map { (value, inst, label) => s"$label=${inst.asInstanceOf[Debuggable[Any]].debug(value)}" } parts.mkString(s"${toSnakeCase(typeName)}{", ", ", "}") private def sumDebuggable[T]( instances: List[Debuggable[?]], s: Mirror.SumOf[T] ): Debuggable[T] = new Debuggable[T]: extension (x: T) def debug: String = val ord = s.ordinal(x) instances(ord).asInstanceOf[Debuggable[Any]].debug(x) private def toSnakeCase(name: String): String = s" $name " .sliding(3) .flatMap { window => val prev = window.charAt(0); val c = window.charAt(1); val next = window.charAt(2) val boundary = c.isUpper && (prev.isLower || prev.isDigit || (prev.isUpper && next.isLower)) (if boundary then "_" else "") + c.toLower } .mkString given Debuggable[Int] with extension (x: Int) def debug: String = x.toString given Debuggable[Long] with extension (x: Long) def debug: String = x.toString given Debuggable[Double] with extension (x: Double) def debug: String = x.toString given Debuggable[Float] with extension (x: Float) def debug: String = x.toString given Debuggable[Boolean] with extension (x: Boolean) def debug: String = x.toString given Debuggable[String] with extension (x: String) def debug: String = x given [T](using d: Debuggable[T]): Debuggable[List[T]] with extension (x: List[T]) def debug: String = x.map(_.debug).mkString("[", ", ", "]") given [T](using d: Debuggable[T]): Debuggable[Option[T]] with extension (x: Option[T]) def debug: String = x match case Some(v) => v.debug case None => "none" case class DebugArg(rendered: String) object DebugArg: given convert[T](using d: Debuggable[T]): Conversion[T, DebugArg] with def apply(x: T): DebugArg = DebugArg(x.debug) extension (sc: StringContext) def debug(args: DebugArg*): String = sc.s(args.map(_.rendered)*) import Debuggable.given case class Person(name: String, age: Int) derives Debuggable enum Shape derives Debuggable: case Circle(radius: Double) case Rectangle(width: Double, height: Double) case Dot @main def run(): Unit = val alice = Person("Alice", 30) val bob = Person("Bob", 25) val circle = Shape.Circle(1.5) val rect = Shape.Rectangle(3.0, 4.0) val dot = Shape.Dot println(alice.debug) println((circle: Shape).debug) println((rect: Shape).debug) println((dot: Shape).debug) println(List(alice, bob).debug) println(Some(alice).debug) println((None: Option[Person]).debug) println(debug"user=$alice, shape=$circle") println(debug"shapes=${List(circle: Shape, rect: Shape, dot: Shape)}")