Skip to content

Instantly share code, notes, and snippets.

@dacr
Last active April 2, 2023 10:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dacr/dd676f8cb50fa668918109b8de617e98 to your computer and use it in GitHub Desktop.
Save dacr/dd676f8cb50fa668918109b8de617e98 to your computer and use it in GitHub Desktop.
scala3 feature examples - opaque types / published by https://github.com/dacr/code-examples-manager #f51b97ee-6fe7-4c76-bc8d-837c7eff6d9e/3ba7febae9ea4c61bcf51090ecd778ea76968d2b
// summary : scala3 feature examples - opaque types
// keywords : scala3, tutorial, @testable
// publish : gist
// authors : David Crosson
// license : Apache NON-AI License Version 2.0 (https://raw.githubusercontent.com/non-ai-licenses/non-ai-licenses/main/NON-AI-APACHE2)
// id : f51b97ee-6fe7-4c76-bc8d-837c7eff6d9e
// created-on : 2021-03-19T17:06:38+01:00
// managed-by : https://github.com/dacr/code-examples-manager
// run-with : scala-cli $file
//> using scala "3.1.1"
/*
The perfect feature for Domain Driven Design (DDD) without overhead
*/
import java.util.UUID
import scala.util.Try
object ProjectDefinitions {
// -- INSIDE OPAQUE TYPES DEFINITIONS SCOPE OPAQUE TYPE RESTRICTION DOESN'T APPLY
opaque type Email = String
opaque type UserId = UUID
object Email {
def fromString(email: String): Option[Email] = if (checkEmail(email)) Some(email) else None
def checkEmail(email: String): Boolean = email.matches("""^[A-Za-z0-9+_.-]+@(.+)$""")
}
object UserId {
def fromString(id: String): Option[UserId] = Try(UUID.fromString(id)).toOption
}
}
@main def go() = {
import ProjectDefinitions.*
// -- OUTSIDE OPAQUE TYPES DEFINITIONS SCOPE OPAQUE TYPE RESTRICTION DOES APPLY SO :
//val myemail:Email = "toto@truc.bidule@@" // it should fail
//val e1:String = Email.fromString("toto@truc.com").get // it should fail
//val e2:Email = "toto@truc.com" // it should fail
Email.fromString("toto@truc.com") match {
case None => println("Invalid mail")
case Some(email) => println(email)
}
// UUID::version is invisible as type is opaque so no way to have access to its internals
UserId.fromString("deadbeef-dead-cafe-dead-beefdeadcafe") match {
case None => println("Invalid userId")
case Some(userId) => println(userId)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment