When I first saw Scala generic type and multiple-parameter group code like this ~12 years ago, my initial thought was, “Wow, maybe I need to think about a different career”:
def race[A, B](lh: IO[A], rh: IO[B])(implicit cs: ContextShift[IO]): IO[Either[A, B]]
But in the end, as Rocky once said, it ain’t so bad. :)
(Image courtesy of the movie, Rocky III.)
In the following sections I’ll show how I break method signatures like this down in my mind these days.
1) See the different groups
First, train yourself to see the different groups in the Scala method signature. Here I separate the groups slightly and color-code them:
(Maybe an IDE can do this for you? If not, it should!)
2) `def` means you’re about to see a method definition
Next, start looking at each group, one at a time. In the first group, def
says, “You’re about to see a method definition”:
3) And then the method name
Next, race
is the name of the method:
(Note that this is a method that “races” two calculations, and returns the winner of that race.)
4) Warning, generic types ahead
In the third group, [A, B]
is the Scala way to say, “In the rest of this type signature, you’re going to see two generic types. We use A
and B
because the types may be different”:
In some cases the types that are supplied may be the same, but because they can be different, we use A and B to note that they can be different.
Also, if we had one type we’d write [A]
, and if there are three types we’d write [A, B, C]
, etc.
(When generic types cause my brain problems, I replace them with something simpler, like Int
and String
.)
5) The first of two parameter groups
Scala lets you have two parameter groups, and the green group shows two parameters named lh
and rh
:
If the name IO
or IO[A]
causes your brain pain, it can help to temporarily think of the types as being Option[Int]
and Option[String]
, or maybe List[Int]
and List[String]
; anything that’s easier to grok at the moment.
6) The second parameter group (and an implicit)
The second parameter group is shown in blue. This one says there is a parameter named cs
that has the type ContextShift[IO]
. The parameter is implicit
, meaning a called can provide it explicitly, or not:
In regard to these parameter groups, the implicit
in Group 2 says, “You can call race
in two different ways in your code”:
// pass the `cs` param explicitly
val result = race(lh, rh)(cs)
// `cs` must be in scope and is pulled in automatically
val result = race(lh, rh)
7) Lastly, the method return type
The race
method returns an IO[Either[A, B]]
:
This is just an Either[A, B]
that’s wrapped in an IO
for safe keeping.
Either
is a construct that returns one of two possible types, so in your code you just need to unwrap the IO
to get the Either
contents. This is like getting a gift that’s in a box, and when you open the first box you find a second box inside, and then your gift is inside that second box.
Think of IO as being an effect or action
In this particular example, IO is a little outside the scope of this discussion, but if it helps, you can think of IO
as being the holder/result of an effect or action. When running effects, libraries like Cats use the term also use the term “unsafe.” Therefore, it may help to think of synonyms for IO
, like these:
Effect[Either[A, B]]
EffectHolder[Either[A, B]]
EffectResult[Either[A, B]]
ActionResult[Either[A, B]]
ResultOfAnAction[Either[A, B]]
Unsafe[Either[A, B]]
For more on IO
, and Either
, see my articles:
- What do effect and effectful mean in functional programming?
- A Scala Either, Left, and Right example
this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |
Summary: Seeing the entire “race” method signature
As I mentioned before, this is a method that “races” two effects, and returns the winner of that race. Hopefully now you can see that all of this is expressed in the method’s type signature. Everything the method needs goes into its two parameter groups, and its result is contained inside the IO
:
And finally, if method signatures like these have made you think about a career change, I hope this helps. :)
More information
If you like videos, see my free video on “How to use multiple parameter groups and call by name parameters in Scala”.