Why ADT?
(If you want to get straight to the solution, just click this.)
If you do Functional Programming in Scala, you probably write lots of Algebraic Data Types (ADT). If you're not sure what it is or why we use or what benefits it offers, here is a good blog post written by Charles O'farrell about The Expression Tradeoff which can give you a good idea of why we use ADT. I strongly recommend reading it.
Writing ADTs in Scala can be annoying as it requires to write data constructor methods the reason of which is explained in The Expression Tradeoff. Again please read it first.
Another Issue with ADT without Constructor Methods
Another reason why constructor methods are better is that it can avoid unwanted type inference.
For instance, if you have an ADT like this.
sealed trait MyType
object MyType {
final case class Foo(n: Int) extends MyType
final case object Bar extends MyType
}
and put the data in a List
List(MyType.Foo(1), MyType.Bar) // List[Product with MyType with Serializable]
The inferred type of the List
is not List[MyType]
. It's List[Product with MyType with Serializable]
as Scala compiler tries to infer the common types of the given case class
and case object
. Both case class
and case object
are Product
as well as Serializable
and that's why its inferred type is List[Product with MyType with Serializable]
.
To fix this issue, you can make MyType
Product with Serializable
.
sealed trait MyType extends Product with Serializable
List(MyType.Foo(1), MyType.Bar) // List[MyType]
However, this doesn't still solve the issue with exposing data (case class
and case object
) not type (sealed trait
). So it's better to use constructor methods just like the "The Expression Tradeoff" says
sealed trait MyType
object MyType {
final case class Foo(n: Int) extends MyType
final case object Bar extends MyType
def foo(n: Int): MyType = Foo(n)
def bar: MyType = Bar
}
Although it's a better way, now you have some boilerplate code in every ADT creation.
(NOTE: The issue makes us use constructor methods is solved in Scala 3 as it has a proper ADT support with enum
.)
Save Your Time on ADT Creation with IntelliJ IDEA Live Templates
So what I want to show you is a way to save time on writing ADTs in Scala using IntelliJ IDEA's live templates.
I certainly don't like to spend time on writing that boilerplate code so created an IntelliJ IDEA live template which can create data constructor methods for you. It's done using Groovy script which is a supported template language of IntelliJ IDEA.
Demo
Let's watch the demo first.
As you can see, if you create the type and data you get the constructor methods as well.
Get the Template Settings
Please download the settings jar file.
Download: IntelliJ IDEA Live template settings
If you're worried about what are inside. Just unzip it and have a look. There are a few empty files and only one XML
file called scala-fp.xml
containing the template info.
How to import
Importing live template in the current version of IntelliJ IDEA might be broken. So if the importing feature doesn't work, check out the alternative way at the end of this importing instruction.
File
->Import Settings
- Select the downloaded IntelliJ IDEA ADT template settings file.
- Make sure
Live templates (schemes)
is ticked and press theOK
button.
- Restart the IDEA.
All done.
- If you want to check whether it's imported correctly or not, open the
Preferences
Editor
->Live Templates
-> Expandscala
. If you can seeadt
andadtData
, you're ready to use it.
Now try! Just type adt
in any .scala
file in the IntelliJ IDEA.
adt
to create ADT initially and adtData
to add more data.
Import Manually
First, unzip the downloaded template zip file. Inside the templates
folder, there should be xml
files like
scala3.xml
scala-etc.xml
scala-fp.xml
scala3-fp.xml
In macOs,
cd "$HOME/Library/Application Support/JetBrains"
ls -l
You should see a list of directories like
drwxr-xr-x - username 22 Apr 00:16 IntelliJIdea2021.3
drwxr-xr-x - username 28 Aug 15:56 IntelliJIdea2022.2
Get inside the directory of the IntelliJ IDEA you're currently using. In my case, it's, IntelliJIdea2022.2
.
cd IntelliJIdea2022.2
- Settings
- Settings Repository
Now move to the live template folder.
mkdir -p templates
cd templates
If you're using settings repository
, use the following commands instead.
If you have no idea what settings repository
is, please ignore it.
mkdir -p settingsRepository/repository/templates
cd settingsRepository/repository/templates
Copy the template xml
files from the unzipped templates
to the templates
folder in the IntelliJ IDEA folder.