Retour sur ScalaIO 2024

Le précédent ScalaIO s’était déroulé en Novembre 2022 à Paris, l’édition 2023 manquant à l’appel, c’était avec grand plaisir que nous ayons pu assister à la récente édition qui a pu se faire en ce début d’année, les 15 et 16 Février 2024 à Nantes dans Le Palace, un espace de coworking et d’évènements. Pour rappel ScalaIO est une conférence autour du langage Scala (le langage, des librairies, …), mais pas seulement, on peut y trouver des sujets autour de la programmation fonctionnelle (dans d’autres langages ou non), de data engineering, de communauté, et aussi, ce qui fait beaucoup parler en ce moment, d’intelligence artificielle.

Les talks

A savoir que cette édition, nous retrouvons beaucoup de talks multilingues, beaucoup d’anglais, et certaines en français, et il y en avait pour tous les niveaux, de sujets plus ou moins avancés. Voici un retours sur quelques unes de ces présentations.

Keynote d’ouverture - Une autre introduction aux GADTs de Xavier Van de Woestyne :

Le speaker fait essentiellement du OCaml et du Kotlin cela peut être surprenant pour ceux qui seraient venus assister pour la première fois à ScalaIO, en effet ce n’était pas un sujet purement Scala mais plutôt un sujet d’algèbre/programmation fonctionnelle.

Xavier nous introduit aux Generalized Algebraic Data Types, il nous réexplique d’abord rapidement ce que sont les Product Types et Sum Types, et qu’ils ont tous un cas minimal qui permet de décrire tous les autres Types Product et Sum :

//code repris de la présentation
//cas minimal de Product Type
case class Prod[+A, +B](fst: A, snd: B)

//permet d'écrire ce produit à 4 éléments
val quad = Prod(1, Prod(2, Prod(3, 4)))

//cas minimal de Sum type, qui en fait un Either
enum Sum[+A, +B]:
	case Left(x: A)
	case Right(x: B)

//on peut écrire ce type Triple à partir de notre Sum de la manière suivante
type Triple = Sum[Int, Sum[Double, String]]
val a : Triple = Sum.Left(1)
val b : Triple = Sum.Right(Sum.Left(1.0))
val c : Triple = Sum.Right(Sum.Rigth("1"))

Puis Xavier nous donne cette définition :

“A Generalized Algebraic Data Type is a sum type that allows its contructors to be non-surjective on one or more of its type parameters and introduces local type-equality constraints in pattern-matching branches, making the expression of existential types trivial”

Wow, mais que cela veut-il dire ?

  • a sum type that allows its contructors to be non-surjective on one or more of its type parameters :

Rendre les constructeurs de son Sum Type non-surjectifs sur un ou plus de ses paramètres de types, c’est en quelque sorte limiter ce que peut être le A dans les constructeurs du GADT :

//code repris de la présentation
enum AST[A]:
	case I(x: Int)                                   extends AST[Int]
	case B(x: Boolean)                               extends AST[Boolean]
	case Add(l: AST[Int], r: AST[Int])               extends AST[Int]
	case Mul(l: AST[Int], r: AST[Int])               extends AST[Int]
	case Equal(l: AST[A], r: AST[A])                 extends AST[Boolean]
	case Cond(c: AST[Boolean], t: AST[A], f: AST[A]) extends AST[A]

def eval[A](ast: AST[A]): A =
	import AST.*
	ast match
		case I(x)            => x
		case B(x)            => x
		case Add(l, r)       => eval(l) + eval(r)
		case Mul(l, r)       => eval(l) * eval(r)
		case Equal(l, r)     => eval(l) == eval(r)
		case Cond(c, t, f)   => if(eval(c)) then eval(t) else eval(f)

Xavier nous explique que cet exemple fonctionne en Scala 2, et qu’on pourrait penser que cela suffit à démontrer que l’on gère les GADT, sauf qu’il manque la suite de sa définition. Cet exemple ne suffit donc pas.

  • introduces local type-equality constraints in pattern-matching branches :

L’idée pour comprendre cette partie est alors de trouver le “GADT minimal” pour prouver la définition du dessus, de manière similaire à ce qui a été décrit pour les Product Type et Sum Type.

//code repris de la présentation
//definit l'égalité entre A et B
enum Eq[A, B]:
	case Refl[A]() extends Eq[A, A]
//Le seul constructeur possible est celui qui étend Eq[A, A], donc que A = B

type Z = Int
val a : Eq[Int, String] = Eq.Refl() //ne compile pas
val b : Eq[Int, Int] = Eq.Refl()
val c : Eq[Int, Z] = Eq.Refl()

L’idée est que si l’on peut instancier un Refl, c’est que A et B sont égaux localement.

Pour garantir l’égalité, on a des principes de substitution à respecter :

//code repris de la présentation

//Symmetry
def symmetry[A, B](witness: Eq[A, B]): Eq[B, A] =
	witness match
		case Eq.Refl() => Eq.Refl()

//Transitivity
def transitivity[A, B, C](witnessA: Eq[A, B], witnessB: Eq[B, C]): Eq[A, C] =
	(witnessA, witnessB) match
		case (Eq.Refl(), Eq.Refl()) => Eq.Refl()

//Free Cast
def cast[A, B](witness: Eq[A, B], value: A): B =
	witness match
		case Eq.Refl() => value

//Injectivity
def injectivity[T[_], A, B](witness: Eq[A, B]): Eq[T[A], T[B]] =
	witness match
		case Eq.Refl() => Eq.Refl()

C’est le cas de l’injectivité qui prouve que le cas des égalités locales est correctement implémenté dans le langage, et cela n’était pas possible en Scala 2 en n’utilisant que Eq, cela fonctionne seulement depuis Scala 3. Le support de ce cas est la preuve qu’on a des GADT.

Il nous présentera ensuite des exemples de types existentiels avec les GADT et un cas pour printer des URLs.

Présenté avec humour et enthousiasme avec quelques gentilles piques à Scala (typeclasses), cette Keynote nous met bien dans le bain, en effet nombreux talks de cette édition reprendront, de près ou de loin, de notions vues dans celle-ci.

Pour en savoir plus, retrouvez le replay de cette keynote ici.

Songwriting in Scala - Creating a DSL for writing Music with ADT's de Paul Matthews, la présentation Rock ! :

Pour rester dans le thème des ADT, nous avons eu une présentation très originale de Paul Matthews, dont le parcours est très atypique, en effet c’est une rockstar ! Bassiste du groupe I Am Giant, auteur-compositeur et ingénieur du son, l’industrie changeante etc. il a du trouver un nouveau but, et c’est en obtenant son diplôme en informatique qu’il est devenu un ingénieur Scala.

C’est tout du moins naturel donc que Paul nous fasse une présentation sur le thème de la musique!
L’idée de la présentation est de partir d’ADT qui représente une portion de musique, et d’interpréter un morceau écrit avec ce dernier à l’aide d’un module Scala.js/Tone.js.

C’est en apprenant le Scala, qu’il a d’abord écrit cet ADT

//code repris de la présentation
sealed trait MusicEvent
final case class Note(noteName: NoteName, duration: Duration) extends MusicEvent
final case class Melody(left: MusicEvent, right: MusicEvent)  extends MusicEvent
final case class Harmony(notes: Vector[Note])                 extends MusicEvent
final case class Rest(duration: Duration)                     extends MusicEvent

Puis de fil en aiguille, il nous montre comment il améliore ses différents Product Type, il se rend compte qu’il peut mieux définir certaines classes, en rajouter, ou en y ajoutant plus de paramètres, etc., avec Note par exemple :

//code repris de la présentation
final case class Note(
	pitch: NoteName,
	accidental: Accidental = Natural,
	duration: Duration = Quarter(),
	velocity: Int,
	octave: Int = 3
) extends MusicEvent

À propos de la velocity, il nous explique qu’il avait besoin de “cloisonner” un peu les différents niveau pour modéliser une MIdi Velocity, en effet un Int peut être négatif ou très grand, mais que dans les plages standards il n’est possible que d’être entre 0 et 127, de plus Tone.js lui ne prend que des valeurs entre 0 et 1. La solution qu’il a trouvé est de créer un autre ADT Velocity:

//code repris de la présentation
enum Velocity(val midiVelocity: Int) {
	def getNormalisedVelocity: Double = {(1.0/127) * this.midiVelocity}
	}
case TheSilentTreatment   extends Velocity(0)
case Softest              extends Velocity(10)
case Sof                  extends Velocity(50)
case Medium               extends Velocity(80)
case Assertively          extends Velocity(100)
case Loud                 extends Velocity(115)
case OnFull               extends Velocity(127)
case Napalm               extends Velocity(13335)

Il nous détaillera tout au long du talk chaque définition de classes qu’il a conçues pour représenter un élément musical.

C’était vraiment une bonne présentation pour comprendre la construction ADT d’une manière beaucoup moins abstraite et concrète, avec le bonus d’entendre la musique codée en live et le tout avec beaucoup de passion.

Je vous invite à voir la présentation ici.

Scala 3 Compiler Academy Journey de Anatolii Kmetiuk

À ScalaIO on a aussi des talks communautaires, comme celui d’Anatolii Kmetiuk qui travaille au sein du Scala Center à l’EPFL. Il nous fera un retour d’expérience sur la création du Scala 3 Compiler Academy.

Il nous dira que le plus important dans la création d’un logiciel ce sont les personnes, ce sont eux qui le créent, le maintiennent et qui le gardent à jour, c’est pourquoi ce projet d’académie est né avec l’aspect communautaire mis en avant.

Ce talk peut s’adresser et s’appliquer à n’importe quel projet Open Source qui souhaite développer son aspect communautaire pour in fine agrandir le nombre de mainteneurs.

  • Qu’est - ce que Scala 3 Compiler Academy ?

Il se compose de sessions de Pair programming en ligne avec les équipes principales de Scala 3, principalement sur les sujets de compilateur Scala 3 et notamment ceux visant à corriger le compilateur. Toute personne intéressée par ces sujets peut rejoindre l’équipe, à raison d’environ une session par mois.

  • Le parcours

    L’idée date depuis 2021, puis en 2022 était la phase d’expérimentation pour arriver à une stabilité en 2023.

    • 2021
      • Contexte : COVID ⇒ travail en remote, rester en contact devient plus difficile, Scala 3.0.0 venait de sortir, donc beaucoup de charge sur l’équipe de maintenance (surtout que l’équipe qui s’en occupe est une équipe de recherche dont le but premier n’est pas le support).
      • Cela a d’abord commencé avec des sessions de 2 heures avec surtout du transfert de connaissance avec l’équipe principale le tout en interne, pour être sûr que ce format fonctionne. Le tout en ligne dû au contexte sanitaire de l’époque, ce qui était nouveau pour eux.
      • À chaque session, ils collectaient des retours (ce qui marchait bien, et ce qui ne marchait pas bien) jusqu’à ne plus avoir de retours négatifs.
      • Fun fact : ils cherchaient des outils de conférence qui utilisent le moins de ressources CPU, en effet comme ces ressources étaient utilisés pour la conférence cela empêchait de compiler.
      • Focus sur le contenu des sessions : le temps, le découpage ⇒ la conclusion est le plus simple le mieux, aussi bien pour l’organisateur que pour les participants afin qu’ils comprennent tout de suite le déroulé.

      Ouverture à l’extérieur

      • Communications via Twitter, puis après ajout de Mastodonte, Discord, Slack.
      • Il fallait s’adapter aux horaires mondiaux cette fois ci pour les sessions, les retours étaient toujours collectés.
      • La nouveauté c’est le “onboarding call” à la différence d’en interne, où il faut prendre le temps d’expliquer au volontaire externe ce qu’il faut faire et comment il peut participer et aussi s’il a besoin de guidage.
      • Un autre challenge qui est apparu, c’est l’équilibrage des équipes, certains sont plus experts dans un domaine du compilateur plutôt qu’un autre. Ils font cela via un formulaire Google Form où chacun choisit l’issue sur lequel il veut travailler, et aussi une option sur une autre issue si jamais ils ne peuvent pas être dispatché dans tel équipe.
    • 2022
      • L’idée de cette année était de monter en volume, aussi bien en nombre de fix à résoudre qu’en nombre de participants.
      • Forcément un des problèmes était le temps des mentors.
      • Une chaîne YouTube a été ouverte aussi pour permettre aux personnes d’apprendre.
      • Un template a été créé avec une checklist pour chaque organisation de spree, pour faciliter la création de ceux-ci et libérer de la charge à l’organisateur.
        Ils ont automatisé tout cela via des outils NoCode.
    • 2023 et aujourd’hui
      • Il y a une stabilité de participants, plus de 80 participants uniques ont participé au projet depuis sa naissance en 2021.
      • Aujourd’hui c’est un format de 3 semaines pour chaque spree

Cela était très intéressant de voir comment s’organise le développement autour d’un projet Open Source comme le compilateur Scala, on ne se rend pas forcément compte des difficultés qui peuvent subvenir pour le bon fonctionnement d’un projet comme celui-ci.

Plus de détails dans la vidéo du talk ici.

Et plein d’autres présentations !

Bien sûr, ce n’était qu’un bref aperçu de quelques présentations de ce ScalaIO 2024, vous pouvez retrouver tous les talks sur la chaîne YouTube de ScalaIO.

Le reste, comment c’était ?

Pour cette édition, une seule salle de conférence, et un endroit pour le partage et/ou la pause. De taille plus modeste pour cette itération, la salle était quand même bien remplie surtout que parallèlement se tenait une grève nationale de transport affectant beaucoup la venue de participants, cela était très plaisant de voir toujours autant de monde intéressé par cette conférence, et de manière générale le Scala.

D’autres aspects qui peuvent vous être intéressants :

  • Enchaînement des présentations très fluide, pas de retard, et je n’ai pas vu de problèmes techniques.
  • Le lieu était vraiment très bien, bien placé dans le centre-ville de Nantes, des logements se trouvaient à proximité, donc pas besoin de transports pour y arriver.
  • Les repas étaient vraiment au top pour les midis ainsi que le traiteur pour la Community Party du premier soir qui se déroulait dans les même locaux.
  • Ambiance générale toujours plaisante, tout le monde est accessible et prêt à échanger.

Je remercie beaucoup les organisateurs pour cette édition du ScalaIO, toujours de qualité, et on attend la prochaine session avec impatience !