As a brief Scala note today, in Scala 3 it doesn’t look like there’s a way to use something like a package object to make some initial code available to all sub-packages of a high-level package. That is, I’d like to be able to define some types in a top-level package like this:
com.aa.myapp
and then use it in all sub-packages like these:
com.aa.myapp.model
com.aa.myapp.view
com.aa.myapp.controller
You might be able to still do that with Scala 2 package objects, but those are deprecated in Scala 3 and may go away at any time.
Solution
What I have found that you can do instead is define your code in a “near” top-level package like this:
package com.aa.myapp.predef // <-- note this package name
// i want to use my type names in all ZIO expressions,
// such as writing `ZIO[NoEnv, NoErrors, NoReturnVal]` instead of
// `ZIO[Any, Nothing, Nothing]`:
type NoEnv = Any
type NoErrors = Nothing
type NoReturnVal = Nothing
Then you can import those package contents into your other files:
package com.aa.myapp.model // <-- note this package name
import zio.*
import zio.Console.*
import com.aa.myapp.predef.* // <-- and the import statement
// some ZIO code in here, like this:
val blueprint: ZIO[NoEnv, NumberFormatException, Int] =
for
a <- zMakeInt("1")
b <- zMakeInt("uh oh")
c <- zMakeInt("3")
yield
a + b + c
This has the benefit that it’s more obvious where those types come from, at the expense of having to add an additional import
line everywhere you want to use those new types.
Discussion
Personally, I think I would like to be able to have something like a Predef.scala
file at the root level of my application, where I can define all my custom types for the entire project, but I haven’t thought about what the potentially negative impacts of that could be.
But if you think about it, Scala built-in types like String
, Int
, and functions like println
all come from somewhere, and they are in a Scala Predef.scala
file, so it seems like having a Predef.scala
file for each project could be a good thing.